aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2015-01-18 16:23:48 +0000
committerDimitry Andric <dim@FreeBSD.org>2015-01-18 16:23:48 +0000
commit06d4ba388873e6d1cfa9cd715a8935ecc8cd2097 (patch)
tree3eb853da77d46cc77c4b017525a422f9ddb1385b /include
parent30d791273d07fac9c0c1641a0731191bca6e8606 (diff)
downloadsrc-06d4ba388873e6d1cfa9cd715a8935ecc8cd2097.tar.gz
src-06d4ba388873e6d1cfa9cd715a8935ecc8cd2097.zip
Vendor import of clang RELEASE_360/rc1 tag r226102 (effectively, 3.6.0 RC1):vendor/clang/clang-release_360-r226102
Notes
Notes: svn path=/vendor/clang/dist/; revision=277325 svn path=/vendor/clang/clang-release_360-r226102/; revision=277326; tag=vendor/clang/clang-release_360-r226102
Diffstat (limited to 'include')
-rw-r--r--include/clang-c/BuildSystem.h4
-rw-r--r--include/clang-c/CXCompilationDatabase.h4
-rw-r--r--include/clang-c/CXErrorCode.h4
-rw-r--r--include/clang-c/CXString.h4
-rw-r--r--include/clang-c/Documentation.h4
-rw-r--r--include/clang-c/Index.h201
-rw-r--r--include/clang-c/Platform.h4
-rw-r--r--include/clang/ARCMigrate/ARCMTActions.h12
-rw-r--r--include/clang/ARCMigrate/FileRemapper.h4
-rw-r--r--include/clang/AST/ASTContext.h111
-rw-r--r--include/clang/AST/ASTDiagnostic.h4
-rw-r--r--include/clang/AST/ASTFwd.h5
-rw-r--r--include/clang/AST/ASTLambda.h6
-rw-r--r--include/clang/AST/ASTMutationListener.h6
-rw-r--r--include/clang/AST/ASTTypeTraits.h111
-rw-r--r--include/clang/AST/ASTVector.h23
-rw-r--r--include/clang/AST/Attr.h1
-rw-r--r--include/clang/AST/CanonicalType.h6
-rw-r--r--include/clang/AST/Comment.h10
-rw-r--r--include/clang/AST/CommentBriefParser.h4
-rw-r--r--include/clang/AST/CommentCommandTraits.h10
-rw-r--r--include/clang/AST/CommentDiagnostic.h4
-rw-r--r--include/clang/AST/CommentLexer.h4
-rw-r--r--include/clang/AST/CommentParser.h4
-rw-r--r--include/clang/AST/CommentSema.h6
-rw-r--r--include/clang/AST/DataRecursiveASTVisitor.h103
-rw-r--r--include/clang/AST/Decl.h162
-rw-r--r--include/clang/AST/DeclBase.h21
-rw-r--r--include/clang/AST/DeclCXX.h109
-rw-r--r--include/clang/AST/DeclLookups.h10
-rw-r--r--include/clang/AST/DeclObjC.h9
-rw-r--r--include/clang/AST/DeclOpenMP.h10
-rw-r--r--include/clang/AST/DeclTemplate.h8
-rw-r--r--include/clang/AST/DeclarationName.h1
-rw-r--r--include/clang/AST/DependentDiagnostic.h7
-rw-r--r--include/clang/AST/EvaluatedExprVisitor.h11
-rw-r--r--include/clang/AST/Expr.h128
-rw-r--r--include/clang/AST/ExprCXX.h103
-rw-r--r--include/clang/AST/ExprObjC.h9
-rw-r--r--include/clang/AST/ExternalASTSource.h6
-rw-r--r--include/clang/AST/LambdaCapture.h12
-rw-r--r--include/clang/AST/Mangle.h5
-rw-r--r--include/clang/AST/MangleNumberingContext.h17
-rw-r--r--include/clang/AST/NSAPI.h10
-rw-r--r--include/clang/AST/NestedNameSpecifier.h34
-rw-r--r--include/clang/AST/OpenMPClause.h261
-rw-r--r--include/clang/AST/OperationKinds.h4
-rw-r--r--include/clang/AST/ParentMap.h4
-rw-r--r--include/clang/AST/PrettyPrinter.h4
-rw-r--r--include/clang/AST/RawCommentList.h4
-rw-r--r--include/clang/AST/RecordLayout.h4
-rw-r--r--include/clang/AST/RecursiveASTVisitor.h103
-rw-r--r--include/clang/AST/Stmt.h99
-rw-r--r--include/clang/AST/StmtGraphTraits.h4
-rw-r--r--include/clang/AST/StmtIterator.h4
-rw-r--r--include/clang/AST/StmtOpenMP.h800
-rw-r--r--include/clang/AST/TemplateBase.h16
-rw-r--r--include/clang/AST/Type.h160
-rw-r--r--include/clang/AST/TypeLoc.h4
-rw-r--r--include/clang/AST/TypeOrdering.h4
-rw-r--r--include/clang/AST/UnresolvedSet.h2
-rw-r--r--include/clang/ASTMatchers/ASTMatchFinder.h69
-rw-r--r--include/clang/ASTMatchers/ASTMatchers.h337
-rw-r--r--include/clang/ASTMatchers/ASTMatchersInternal.h636
-rw-r--r--include/clang/ASTMatchers/ASTMatchersMacros.h17
-rw-r--r--include/clang/ASTMatchers/Dynamic/Diagnostics.h4
-rw-r--r--include/clang/ASTMatchers/Dynamic/Parser.h130
-rw-r--r--include/clang/ASTMatchers/Dynamic/Registry.h51
-rw-r--r--include/clang/ASTMatchers/Dynamic/VariantValue.h184
-rw-r--r--include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h4
-rw-r--r--include/clang/Analysis/Analyses/Consumed.h4
-rw-r--r--include/clang/Analysis/Analyses/Dominators.h4
-rw-r--r--include/clang/Analysis/Analyses/FormatString.h10
-rw-r--r--include/clang/Analysis/Analyses/LiveVariables.h4
-rw-r--r--include/clang/Analysis/Analyses/PostOrderCFGView.h12
-rw-r--r--include/clang/Analysis/Analyses/PseudoConstantAnalysis.h4
-rw-r--r--include/clang/Analysis/Analyses/ReachableCode.h4
-rw-r--r--include/clang/Analysis/Analyses/ThreadSafety.h33
-rw-r--r--include/clang/Analysis/Analyses/ThreadSafetyCommon.h140
-rw-r--r--include/clang/Analysis/Analyses/ThreadSafetyLogical.h12
-rw-r--r--include/clang/Analysis/Analyses/ThreadSafetyOps.def3
-rw-r--r--include/clang/Analysis/Analyses/ThreadSafetyTIL.h1107
-rw-r--r--include/clang/Analysis/Analyses/ThreadSafetyTraverse.h450
-rw-r--r--include/clang/Analysis/Analyses/ThreadSafetyUtil.h68
-rw-r--r--include/clang/Analysis/Analyses/UninitializedValues.h4
-rw-r--r--include/clang/Analysis/AnalysisContext.h16
-rw-r--r--include/clang/Analysis/AnalysisDiagnostic.h4
-rw-r--r--include/clang/Analysis/CFG.h11
-rw-r--r--include/clang/Analysis/CFGStmtMap.h4
-rw-r--r--include/clang/Analysis/CallGraph.h4
-rw-r--r--include/clang/Analysis/CodeInjector.h46
-rw-r--r--include/clang/Analysis/DomainSpecific/CocoaConventions.h4
-rw-r--r--include/clang/Analysis/DomainSpecific/ObjCNoReturn.h4
-rw-r--r--include/clang/Analysis/ProgramPoint.h4
-rw-r--r--include/clang/Analysis/Support/BumpVector.h6
-rw-r--r--include/clang/Basic/ABI.h11
-rw-r--r--include/clang/Basic/AddressSpaces.h1
-rw-r--r--include/clang/Basic/AllDiagnostics.h4
-rw-r--r--include/clang/Basic/Attr.td246
-rw-r--r--include/clang/Basic/AttrDocs.td338
-rw-r--r--include/clang/Basic/AttrKinds.h4
-rw-r--r--include/clang/Basic/Attributes.h14
-rw-r--r--include/clang/Basic/Builtins.def19
-rw-r--r--include/clang/Basic/Builtins.h4
-rw-r--r--include/clang/Basic/BuiltinsAArch64.def3
-rw-r--r--include/clang/Basic/BuiltinsARM.def6
-rw-r--r--include/clang/Basic/BuiltinsLe64.def19
-rw-r--r--include/clang/Basic/BuiltinsNVPTX.def30
-rw-r--r--include/clang/Basic/BuiltinsPPC.def19
-rw-r--r--include/clang/Basic/BuiltinsR600.def8
-rw-r--r--include/clang/Basic/BuiltinsX86.def207
-rw-r--r--include/clang/Basic/CharInfo.h4
-rw-r--r--include/clang/Basic/CommentOptions.h4
-rw-r--r--include/clang/Basic/Diagnostic.h16
-rw-r--r--include/clang/Basic/DiagnosticASTKinds.td7
-rw-r--r--include/clang/Basic/DiagnosticCommonKinds.td14
-rw-r--r--include/clang/Basic/DiagnosticDriverKinds.td18
-rw-r--r--include/clang/Basic/DiagnosticFrontendKinds.td34
-rw-r--r--include/clang/Basic/DiagnosticGroups.td75
-rw-r--r--include/clang/Basic/DiagnosticIDs.h6
-rw-r--r--include/clang/Basic/DiagnosticLexKinds.td25
-rw-r--r--include/clang/Basic/DiagnosticOptions.def3
-rw-r--r--include/clang/Basic/DiagnosticOptions.h3
-rw-r--r--include/clang/Basic/DiagnosticParseKinds.td115
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td444
-rw-r--r--include/clang/Basic/DiagnosticSerializationKinds.td10
-rw-r--r--include/clang/Basic/ExceptionSpecificationType.h3
-rw-r--r--include/clang/Basic/ExpressionTraits.h4
-rw-r--r--include/clang/Basic/FileManager.h25
-rw-r--r--include/clang/Basic/FileSystemStatCache.h12
-rw-r--r--include/clang/Basic/IdentifierTable.h65
-rw-r--r--include/clang/Basic/LLVM.h4
-rw-r--r--include/clang/Basic/Lambda.h3
-rw-r--r--include/clang/Basic/LangOptions.def68
-rw-r--r--include/clang/Basic/LangOptions.h26
-rw-r--r--include/clang/Basic/Module.h52
-rw-r--r--include/clang/Basic/ObjCRuntime.h4
-rw-r--r--include/clang/Basic/OpenMPKinds.def79
-rw-r--r--include/clang/Basic/OpenMPKinds.h6
-rw-r--r--include/clang/Basic/OperatorKinds.h4
-rw-r--r--include/clang/Basic/OperatorPrecedence.h4
-rw-r--r--include/clang/Basic/PartialDiagnostic.h4
-rw-r--r--include/clang/Basic/PlistSupport.h4
-rw-r--r--include/clang/Basic/PrettyStackTrace.h4
-rw-r--r--include/clang/Basic/SanitizerBlacklist.h45
-rw-r--r--include/clang/Basic/Sanitizers.def19
-rw-r--r--include/clang/Basic/Sanitizers.h47
-rw-r--r--include/clang/Basic/SourceLocation.h5
-rw-r--r--include/clang/Basic/SourceManager.h31
-rw-r--r--include/clang/Basic/SourceManagerInternals.h4
-rw-r--r--include/clang/Basic/Specifiers.h11
-rw-r--r--include/clang/Basic/StmtNodes.td15
-rw-r--r--include/clang/Basic/TargetBuiltins.h15
-rw-r--r--include/clang/Basic/TargetCXXABI.h4
-rw-r--r--include/clang/Basic/TargetInfo.h52
-rw-r--r--include/clang/Basic/TargetOptions.h4
-rw-r--r--include/clang/Basic/TemplateKinds.h4
-rw-r--r--include/clang/Basic/TokenKinds.def14
-rw-r--r--include/clang/Basic/TokenKinds.h10
-rw-r--r--include/clang/Basic/TypeTraits.h4
-rw-r--r--include/clang/Basic/VersionTuple.h29
-rw-r--r--include/clang/Basic/VirtualFileSystem.h36
-rw-r--r--include/clang/Basic/arm_neon.td49
-rw-r--r--include/clang/CodeGen/BackendUtil.h4
-rw-r--r--include/clang/CodeGen/CGFunctionInfo.h35
-rw-r--r--include/clang/CodeGen/CodeGenABITypes.h8
-rw-r--r--include/clang/CodeGen/CodeGenAction.h14
-rw-r--r--include/clang/CodeGen/ModuleBuilder.h4
-rw-r--r--include/clang/Config/config.h.cmake6
-rw-r--r--include/clang/Config/config.h.in9
-rw-r--r--include/clang/Driver/Action.h46
-rw-r--r--include/clang/Driver/CC1Options.td29
-rw-r--r--include/clang/Driver/CLCompatOptions.td30
-rw-r--r--include/clang/Driver/Compilation.h6
-rw-r--r--include/clang/Driver/Driver.h32
-rw-r--r--include/clang/Driver/DriverDiagnostic.h4
-rw-r--r--include/clang/Driver/Job.h70
-rw-r--r--include/clang/Driver/Multilib.h16
-rw-r--r--include/clang/Driver/Options.h4
-rw-r--r--include/clang/Driver/Options.td179
-rw-r--r--include/clang/Driver/Phases.h5
-rw-r--r--include/clang/Driver/SanitizerArgs.h126
-rw-r--r--include/clang/Driver/Tool.h62
-rw-r--r--include/clang/Driver/ToolChain.h14
-rw-r--r--include/clang/Driver/Types.h4
-rw-r--r--include/clang/Driver/Util.h4
-rw-r--r--include/clang/Format/Format.h99
-rw-r--r--include/clang/Frontend/ASTConsumers.h18
-rw-r--r--include/clang/Frontend/ASTUnit.h57
-rw-r--r--include/clang/Frontend/ChainedDiagnosticConsumer.h17
-rw-r--r--include/clang/Frontend/CodeGenOptions.def14
-rw-r--r--include/clang/Frontend/CodeGenOptions.h25
-rw-r--r--include/clang/Frontend/CompilerInstance.h38
-rw-r--r--include/clang/Frontend/DiagnosticRenderer.h4
-rw-r--r--include/clang/Frontend/FrontendAction.h41
-rw-r--r--include/clang/Frontend/FrontendActions.h51
-rw-r--r--include/clang/Frontend/FrontendDiagnostic.h4
-rw-r--r--include/clang/Frontend/FrontendOptions.h16
-rw-r--r--include/clang/Frontend/FrontendPluginRegistry.h4
-rw-r--r--include/clang/Frontend/LangStandard.h6
-rw-r--r--include/clang/Frontend/LangStandards.def15
-rw-r--r--include/clang/Frontend/LogDiagnosticPrinter.h15
-rw-r--r--include/clang/Frontend/MigratorOptions.h4
-rw-r--r--include/clang/Frontend/MultiplexConsumer.h8
-rw-r--r--include/clang/Frontend/SerializedDiagnosticPrinter.h45
-rw-r--r--include/clang/Frontend/SerializedDiagnosticReader.h131
-rw-r--r--include/clang/Frontend/SerializedDiagnostics.h59
-rw-r--r--include/clang/Frontend/TextDiagnostic.h4
-rw-r--r--include/clang/Frontend/TextDiagnosticBuffer.h4
-rw-r--r--include/clang/Frontend/TextDiagnosticPrinter.h4
-rw-r--r--include/clang/Frontend/Utils.h5
-rw-r--r--include/clang/Frontend/VerifyDiagnosticConsumer.h27
-rw-r--r--include/clang/Lex/ExternalPreprocessorSource.h6
-rw-r--r--include/clang/Lex/HeaderMap.h10
-rw-r--r--include/clang/Lex/HeaderSearch.h29
-rw-r--r--include/clang/Lex/HeaderSearchOptions.h13
-rw-r--r--include/clang/Lex/LexDiagnostic.h4
-rw-r--r--include/clang/Lex/Lexer.h10
-rw-r--r--include/clang/Lex/LiteralSupport.h4
-rw-r--r--include/clang/Lex/MacroArgs.h4
-rw-r--r--include/clang/Lex/MacroInfo.h119
-rw-r--r--include/clang/Lex/ModuleLoader.h4
-rw-r--r--include/clang/Lex/ModuleMap.h116
-rw-r--r--include/clang/Lex/MultipleIncludeOpt.h4
-rw-r--r--include/clang/Lex/PPCallbacks.h11
-rw-r--r--include/clang/Lex/PTHLexer.h4
-rw-r--r--include/clang/Lex/PTHManager.h32
-rw-r--r--include/clang/Lex/Pragma.h4
-rw-r--r--include/clang/Lex/Preprocessor.h103
-rw-r--r--include/clang/Lex/PreprocessorLexer.h4
-rw-r--r--include/clang/Lex/ScratchBuffer.h4
-rw-r--r--include/clang/Lex/Token.h29
-rw-r--r--include/clang/Lex/TokenConcatenation.h4
-rw-r--r--include/clang/Lex/TokenLexer.h4
-rw-r--r--include/clang/Parse/ParseDiagnostic.h4
-rw-r--r--include/clang/Parse/Parser.h103
-rw-r--r--include/clang/Rewrite/Core/DeltaTree.h4
-rw-r--r--include/clang/Rewrite/Core/HTMLRewrite.h4
-rw-r--r--include/clang/Rewrite/Core/RewriteRope.h52
-rw-r--r--include/clang/Rewrite/Core/Rewriter.h14
-rw-r--r--include/clang/Rewrite/Core/TokenRewriter.h4
-rw-r--r--include/clang/Rewrite/Frontend/ASTConsumers.h31
-rw-r--r--include/clang/Rewrite/Frontend/FixItRewriter.h8
-rw-r--r--include/clang/Rewrite/Frontend/FrontendActions.h16
-rw-r--r--include/clang/Rewrite/Frontend/Rewriters.h4
-rw-r--r--include/clang/Sema/AnalysisBasedWarnings.h4
-rw-r--r--include/clang/Sema/AttributeList.h15
-rw-r--r--include/clang/Sema/DeclSpec.h58
-rw-r--r--include/clang/Sema/DelayedDiagnostic.h4
-rw-r--r--include/clang/Sema/ExternalSemaSource.h17
-rw-r--r--include/clang/Sema/IdentifierResolver.h4
-rw-r--r--include/clang/Sema/Lookup.h27
-rw-r--r--include/clang/Sema/LoopHint.h13
-rw-r--r--include/clang/Sema/MultiplexExternalSemaSource.h15
-rw-r--r--include/clang/Sema/ObjCMethodList.h31
-rw-r--r--include/clang/Sema/Overload.h36
-rw-r--r--include/clang/Sema/PrettyDeclStackTrace.h4
-rw-r--r--include/clang/Sema/Scope.h20
-rw-r--r--include/clang/Sema/ScopeInfo.h41
-rw-r--r--include/clang/Sema/Sema.h485
-rw-r--r--include/clang/Sema/SemaDiagnostic.h4
-rw-r--r--include/clang/Sema/SemaFixItUtils.h6
-rw-r--r--include/clang/Sema/SemaInternal.h212
-rw-r--r--include/clang/Sema/SemaLambda.h6
-rw-r--r--include/clang/Sema/TemplateDeduction.h4
-rw-r--r--include/clang/Sema/TypoCorrection.h42
-rw-r--r--include/clang/Serialization/ASTBitCodes.h41
-rw-r--r--include/clang/Serialization/ASTDeserializationListener.h4
-rw-r--r--include/clang/Serialization/ASTReader.h133
-rw-r--r--include/clang/Serialization/ASTWriter.h67
-rw-r--r--include/clang/Serialization/ContinuousRangeMap.h12
-rw-r--r--include/clang/Serialization/GlobalModuleIndex.h6
-rw-r--r--include/clang/Serialization/Module.h18
-rw-r--r--include/clang/Serialization/ModuleManager.h23
-rw-r--r--include/clang/Serialization/SerializationDiagnostic.h4
-rw-r--r--include/clang/StaticAnalyzer/Checkers/LocalCheckers.h4
-rw-r--r--include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h14
-rw-r--r--include/clang/StaticAnalyzer/Core/AnalyzerOptions.h12
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h21
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h30
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/BugType.h4
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h4
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h12
-rw-r--r--include/clang/StaticAnalyzer/Core/Checker.h4
-rw-r--r--include/clang/StaticAnalyzer/Core/CheckerManager.h4
-rw-r--r--include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h4
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h4
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h9
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h4
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h4
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h4
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h4
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h4
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h9
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h23
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h4
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h4
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h15
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h19
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h4
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h4
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h11
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h4
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h4
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h4
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h4
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/Store.h10
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h4
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h14
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h4
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h4
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h4
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h4
-rw-r--r--include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h12
-rw-r--r--include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h12
-rw-r--r--include/clang/StaticAnalyzer/Frontend/FrontendActions.h33
-rw-r--r--include/clang/StaticAnalyzer/Frontend/ModelConsumer.h44
-rw-r--r--include/clang/Tooling/ArgumentsAdjusters.h68
-rw-r--r--include/clang/Tooling/CommonOptionsParser.h6
-rw-r--r--include/clang/Tooling/CompilationDatabase.h22
-rw-r--r--include/clang/Tooling/CompilationDatabasePluginRegistry.h6
-rw-r--r--include/clang/Tooling/Core/Replacement.h229
-rw-r--r--include/clang/Tooling/FileMatchTrie.h6
-rw-r--r--include/clang/Tooling/JSONCompilationDatabase.h19
-rw-r--r--include/clang/Tooling/Refactoring.h176
-rw-r--r--include/clang/Tooling/RefactoringCallbacks.h6
-rw-r--r--include/clang/Tooling/ReplacementsYaml.h6
-rw-r--r--include/clang/Tooling/Tooling.h42
-rw-r--r--include/clang/module.modulemap25
329 files changed, 9487 insertions, 3754 deletions
diff --git a/include/clang-c/BuildSystem.h b/include/clang-c/BuildSystem.h
index ed3e8d9a28b3..7aa01914cf24 100644
--- a/include/clang-c/BuildSystem.h
+++ b/include/clang-c/BuildSystem.h
@@ -11,8 +11,8 @@
|* *|
\*===----------------------------------------------------------------------===*/
-#ifndef CLANG_C_BUILD_SYSTEM_H
-#define CLANG_C_BUILD_SYSTEM_H
+#ifndef LLVM_CLANG_C_BUILDSYSTEM_H
+#define LLVM_CLANG_C_BUILDSYSTEM_H
#include "clang-c/Platform.h"
#include "clang-c/CXErrorCode.h"
diff --git a/include/clang-c/CXCompilationDatabase.h b/include/clang-c/CXCompilationDatabase.h
index fd65418f607c..068a677a95ed 100644
--- a/include/clang-c/CXCompilationDatabase.h
+++ b/include/clang-c/CXCompilationDatabase.h
@@ -12,8 +12,8 @@
|* *|
\*===----------------------------------------------------------------------===*/
-#ifndef CLANG_CXCOMPILATIONDATABASE_H
-#define CLANG_CXCOMPILATIONDATABASE_H
+#ifndef LLVM_CLANG_C_CXCOMPILATIONDATABASE_H
+#define LLVM_CLANG_C_CXCOMPILATIONDATABASE_H
#include "clang-c/Platform.h"
#include "clang-c/CXString.h"
diff --git a/include/clang-c/CXErrorCode.h b/include/clang-c/CXErrorCode.h
index a026c95a5bb9..aff73b746763 100644
--- a/include/clang-c/CXErrorCode.h
+++ b/include/clang-c/CXErrorCode.h
@@ -11,8 +11,8 @@
|* *|
\*===----------------------------------------------------------------------===*/
-#ifndef CLANG_C_CXERRORCODE_H
-#define CLANG_C_CXERRORCODE_H
+#ifndef LLVM_CLANG_C_CXERRORCODE_H
+#define LLVM_CLANG_C_CXERRORCODE_H
#include "clang-c/Platform.h"
diff --git a/include/clang-c/CXString.h b/include/clang-c/CXString.h
index cf198cbf5d0f..a649cdf82fc7 100644
--- a/include/clang-c/CXString.h
+++ b/include/clang-c/CXString.h
@@ -11,8 +11,8 @@
|* *|
\*===----------------------------------------------------------------------===*/
-#ifndef CLANG_CXSTRING_H
-#define CLANG_CXSTRING_H
+#ifndef LLVM_CLANG_C_CXSTRING_H
+#define LLVM_CLANG_C_CXSTRING_H
#include "clang-c/Platform.h"
diff --git a/include/clang-c/Documentation.h b/include/clang-c/Documentation.h
index ad2da0778315..89373b11457d 100644
--- a/include/clang-c/Documentation.h
+++ b/include/clang-c/Documentation.h
@@ -12,8 +12,8 @@
|* *|
\*===----------------------------------------------------------------------===*/
-#ifndef CLANG_C_DOCUMENTATION_H
-#define CLANG_C_DOCUMENTATION_H
+#ifndef LLVM_CLANG_C_DOCUMENTATION_H
+#define LLVM_CLANG_C_DOCUMENTATION_H
#include "clang-c/Index.h"
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h
index f69f567c2690..ed7bd169f6fc 100644
--- a/include/clang-c/Index.h
+++ b/include/clang-c/Index.h
@@ -13,8 +13,8 @@
|* *|
\*===----------------------------------------------------------------------===*/
-#ifndef CLANG_C_INDEX_H
-#define CLANG_C_INDEX_H
+#ifndef LLVM_CLANG_C_INDEX_H
+#define LLVM_CLANG_C_INDEX_H
#include <time.h>
@@ -32,7 +32,7 @@
* compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable.
*/
#define CINDEX_VERSION_MAJOR 0
-#define CINDEX_VERSION_MINOR 27
+#define CINDEX_VERSION_MINOR 29
#define CINDEX_VERSION_ENCODE(major, minor) ( \
((major) * 10000) \
@@ -336,6 +336,12 @@ CINDEX_LINKAGE CXFile clang_getFile(CXTranslationUnit tu,
const char *file_name);
/**
+ * \brief Returns non-zero if the \c file1 and \c file2 point to the same file,
+ * or they are both NULL.
+ */
+CINDEX_LINKAGE int clang_File_isEqual(CXFile file1, CXFile file2);
+
+/**
* @}
*/
@@ -2120,7 +2126,7 @@ enum CXCursorKind {
*/
CXCursor_MSAsmStmt = 229,
- /** \brief The null satement ";": C99 6.8.3p3.
+ /** \brief The null statement ";": C99 6.8.3p3.
*
* This cursor kind is used to describe the null statement.
*/
@@ -2135,7 +2141,7 @@ enum CXCursorKind {
*/
CXCursor_OMPParallelDirective = 232,
- /** \brief OpenMP simd directive.
+ /** \brief OpenMP SIMD directive.
*/
CXCursor_OMPSimdDirective = 233,
@@ -2195,7 +2201,31 @@ enum CXCursorKind {
*/
CXCursor_SEHLeaveStmt = 247,
- CXCursor_LastStmt = CXCursor_SEHLeaveStmt,
+ /** \brief OpenMP ordered directive.
+ */
+ CXCursor_OMPOrderedDirective = 248,
+
+ /** \brief OpenMP atomic directive.
+ */
+ CXCursor_OMPAtomicDirective = 249,
+
+ /** \brief OpenMP for SIMD directive.
+ */
+ CXCursor_OMPForSimdDirective = 250,
+
+ /** \brief OpenMP parallel for SIMD directive.
+ */
+ CXCursor_OMPParallelForSimdDirective = 251,
+
+ /** \brief OpenMP target directive.
+ */
+ CXCursor_OMPTargetDirective = 252,
+
+ /** \brief OpenMP teams directive.
+ */
+ CXCursor_OMPTeamsDirective = 253,
+
+ CXCursor_LastStmt = CXCursor_OMPTeamsDirective,
/**
* \brief Cursor that represents the translation unit itself.
@@ -2228,7 +2258,8 @@ enum CXCursorKind {
CXCursor_CUDADeviceAttr = 413,
CXCursor_CUDAGlobalAttr = 414,
CXCursor_CUDAHostAttr = 415,
- CXCursor_LastAttr = CXCursor_CUDAHostAttr,
+ CXCursor_CUDASharedAttr = 416,
+ CXCursor_LastAttr = CXCursor_CUDASharedAttr,
/* Preprocessing */
CXCursor_PreprocessingDirective = 500,
@@ -2822,6 +2853,7 @@ enum CXCallingConv {
CXCallingConv_IntelOclBicc = 9,
CXCallingConv_X86_64Win64 = 10,
CXCallingConv_X86_64SysV = 11,
+ CXCallingConv_X86VectorCall = 12,
CXCallingConv_Invalid = 100,
CXCallingConv_Unexposed = 200
@@ -2912,6 +2944,124 @@ CINDEX_LINKAGE int clang_Cursor_getNumArguments(CXCursor C);
CINDEX_LINKAGE CXCursor clang_Cursor_getArgument(CXCursor C, unsigned i);
/**
+ * \brief Describes the kind of a template argument.
+ *
+ * See the definition of llvm::clang::TemplateArgument::ArgKind for full
+ * element descriptions.
+ */
+enum CXTemplateArgumentKind {
+ CXTemplateArgumentKind_Null,
+ CXTemplateArgumentKind_Type,
+ CXTemplateArgumentKind_Declaration,
+ CXTemplateArgumentKind_NullPtr,
+ CXTemplateArgumentKind_Integral,
+ CXTemplateArgumentKind_Template,
+ CXTemplateArgumentKind_TemplateExpansion,
+ CXTemplateArgumentKind_Expression,
+ CXTemplateArgumentKind_Pack,
+ /* Indicates an error case, preventing the kind from being deduced. */
+ CXTemplateArgumentKind_Invalid
+};
+
+/**
+ *\brief Returns the number of template args of a function decl representing a
+ * template specialization.
+ *
+ * If the argument cursor cannot be converted into a template function
+ * declaration, -1 is returned.
+ *
+ * For example, for the following declaration and specialization:
+ * template <typename T, int kInt, bool kBool>
+ * void foo() { ... }
+ *
+ * template <>
+ * void foo<float, -7, true>();
+ *
+ * The value 3 would be returned from this call.
+ */
+CINDEX_LINKAGE int clang_Cursor_getNumTemplateArguments(CXCursor C);
+
+/**
+ * \brief Retrieve the kind of the I'th template argument of the CXCursor C.
+ *
+ * If the argument CXCursor does not represent a FunctionDecl, an invalid
+ * template argument kind is returned.
+ *
+ * For example, for the following declaration and specialization:
+ * template <typename T, int kInt, bool kBool>
+ * void foo() { ... }
+ *
+ * template <>
+ * void foo<float, -7, true>();
+ *
+ * For I = 0, 1, and 2, Type, Integral, and Integral will be returned,
+ * respectively.
+ */
+CINDEX_LINKAGE enum CXTemplateArgumentKind clang_Cursor_getTemplateArgumentKind(
+ CXCursor C, unsigned I);
+
+/**
+ * \brief Retrieve a CXType representing the type of a TemplateArgument of a
+ * function decl representing a template specialization.
+ *
+ * If the argument CXCursor does not represent a FunctionDecl whose I'th
+ * template argument has a kind of CXTemplateArgKind_Integral, an invalid type
+ * is returned.
+ *
+ * For example, for the following declaration and specialization:
+ * template <typename T, int kInt, bool kBool>
+ * void foo() { ... }
+ *
+ * template <>
+ * void foo<float, -7, true>();
+ *
+ * If called with I = 0, "float", will be returned.
+ * Invalid types will be returned for I == 1 or 2.
+ */
+CINDEX_LINKAGE CXType clang_Cursor_getTemplateArgumentType(CXCursor C,
+ unsigned I);
+
+/**
+ * \brief Retrieve the value of an Integral TemplateArgument (of a function
+ * decl representing a template specialization) as a signed long long.
+ *
+ * It is undefined to call this function on a CXCursor that does not represent a
+ * FunctionDecl or whose I'th template argument is not an integral value.
+ *
+ * For example, for the following declaration and specialization:
+ * template <typename T, int kInt, bool kBool>
+ * void foo() { ... }
+ *
+ * template <>
+ * void foo<float, -7, true>();
+ *
+ * If called with I = 1 or 2, -7 or true will be returned, respectively.
+ * For I == 0, this function's behavior is undefined.
+ */
+CINDEX_LINKAGE long long clang_Cursor_getTemplateArgumentValue(CXCursor C,
+ unsigned I);
+
+/**
+ * \brief Retrieve the value of an Integral TemplateArgument (of a function
+ * decl representing a template specialization) as an unsigned long long.
+ *
+ * It is undefined to call this function on a CXCursor that does not represent a
+ * FunctionDecl or whose I'th template argument is not an integral value.
+ *
+ * For example, for the following declaration and specialization:
+ * template <typename T, int kInt, bool kBool>
+ * void foo() { ... }
+ *
+ * template <>
+ * void foo<float, 2147483649, true>();
+ *
+ * If called with I = 1 or 2, 2147483649 or true will be returned, respectively.
+ * For I == 0, this function's behavior is undefined.
+ */
+CINDEX_LINKAGE unsigned long long clang_Cursor_getTemplateArgumentUnsignedValue(
+ CXCursor C, unsigned I);
+
+/**
* \brief Determine whether two CXTypes represent the same type.
*
* \returns non-zero if the CXTypes represent the same type and
@@ -3194,6 +3344,29 @@ enum CX_CXXAccessSpecifier {
CINDEX_LINKAGE enum CX_CXXAccessSpecifier clang_getCXXAccessSpecifier(CXCursor);
/**
+ * \brief Represents the storage classes as declared in the source. CX_SC_Invalid
+ * was added for the case that the passed cursor in not a declaration.
+ */
+enum CX_StorageClass {
+ CX_SC_Invalid,
+ CX_SC_None,
+ CX_SC_Extern,
+ CX_SC_Static,
+ CX_SC_PrivateExtern,
+ CX_SC_OpenCLWorkGroupLocal,
+ CX_SC_Auto,
+ CX_SC_Register
+};
+
+/**
+ * \brief Returns the storage class for a function or variable declaration.
+ *
+ * If the passed in Cursor is not a function or variable declaration,
+ * CX_SC_Invalid is returned else the storage class.
+ */
+CINDEX_LINKAGE enum CX_StorageClass clang_Cursor_getStorageClass(CXCursor);
+
+/**
* \brief Determine the number of overloaded declarations referenced by a
* \c CXCursor_OverloadedDeclRef cursor.
*
@@ -3631,6 +3804,20 @@ CINDEX_LINKAGE CXString clang_Cursor_getBriefCommentText(CXCursor C);
* @}
*/
+/** \defgroup CINDEX_MANGLE Name Mangling API Functions
+ *
+ * @{
+ */
+
+/**
+ * \brief Retrieve the CXString representing the mangled name of the cursor.
+ */
+CINDEX_LINKAGE CXString clang_Cursor_getMangling(CXCursor);
+
+/**
+ * @}
+ */
+
/**
* \defgroup CINDEX_MODULE Module introspection
*
diff --git a/include/clang-c/Platform.h b/include/clang-c/Platform.h
index 0f866c64563c..e2a4dccbdaf0 100644
--- a/include/clang-c/Platform.h
+++ b/include/clang-c/Platform.h
@@ -11,8 +11,8 @@
|* *|
\*===----------------------------------------------------------------------===*/
-#ifndef CLANG_C_PLATFORM_H
-#define CLANG_C_PLATFORM_H
+#ifndef LLVM_CLANG_C_PLATFORM_H
+#define LLVM_CLANG_C_PLATFORM_H
#ifdef __cplusplus
extern "C" {
diff --git a/include/clang/ARCMigrate/ARCMTActions.h b/include/clang/ARCMigrate/ARCMTActions.h
index b3e74b996678..c830aa3d7874 100644
--- a/include/clang/ARCMigrate/ARCMTActions.h
+++ b/include/clang/ARCMigrate/ARCMTActions.h
@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_ARCMIGRATE_ARCMT_ACTION_H
-#define LLVM_CLANG_ARCMIGRATE_ARCMT_ACTION_H
+#ifndef LLVM_CLANG_ARCMIGRATE_ARCMTACTIONS_H
+#define LLVM_CLANG_ARCMIGRATE_ARCMTACTIONS_H
#include "clang/ARCMigrate/FileRemapper.h"
#include "clang/Frontend/FrontendAction.h"
@@ -37,8 +37,8 @@ class MigrateSourceAction : public ASTFrontendAction {
FileRemapper Remapper;
protected:
bool BeginInvocation(CompilerInstance &CI) override;
- ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile) override;
+ std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
};
class MigrateAction : public WrapperFrontendAction {
@@ -65,8 +65,8 @@ public:
unsigned migrateAction);
protected:
- ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile) override;
+ std::unique_ptr<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 e094301ae6c4..53b88e9eb5e5 100644
--- a/include/clang/ARCMigrate/FileRemapper.h
+++ b/include/clang/ARCMigrate/FileRemapper.h
@@ -52,14 +52,14 @@ public:
bool overwriteOriginal(DiagnosticsEngine &Diag,
StringRef outputDir = StringRef());
- void remap(StringRef filePath, llvm::MemoryBuffer *memBuf);
+ void remap(StringRef filePath, std::unique_ptr<llvm::MemoryBuffer> memBuf);
void applyMappings(PreprocessorOptions &PPOpts) const;
void clear(StringRef outputDir = StringRef());
private:
- void remap(const FileEntry *file, llvm::MemoryBuffer *memBuf);
+ void remap(const FileEntry *file, std::unique_ptr<llvm::MemoryBuffer> memBuf);
void remap(const FileEntry *file, const FileEntry *newfile);
const FileEntry *getOriginalFile(StringRef filePath);
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index 8134f6b080b7..195d748b5be8 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -30,6 +30,7 @@
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/SanitizerBlacklist.h"
#include "clang/Basic/VersionTuple.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FoldingSet.h"
@@ -74,6 +75,15 @@ namespace clang {
class FullComment;
}
+ struct TypeInfo {
+ uint64_t Width;
+ unsigned Align;
+ bool AlignIsRequired : 1;
+ TypeInfo() : Width(0), Align(0), AlignIsRequired(false) {}
+ TypeInfo(uint64_t Width, unsigned Align, bool AlignIsRequired)
+ : Width(Width), Align(Align), AlignIsRequired(AlignIsRequired) {}
+ };
+
/// \brief Holds long-lived AST nodes (such as types and decls) that can be
/// referred to throughout the semantic analysis of a file.
class ASTContext : public RefCountedBase<ASTContext> {
@@ -144,8 +154,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
ObjCLayouts;
/// \brief A cache from types to size and alignment information.
- typedef llvm::DenseMap<const Type*,
- std::pair<uint64_t, unsigned> > TypeInfoMap;
+ typedef llvm::DenseMap<const Type *, struct TypeInfo> TypeInfoMap;
mutable TypeInfoMap MemoizedTypeInfo;
/// \brief A cache mapping from CXXRecordDecls to key functions.
@@ -264,8 +273,6 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// \brief Declaration for the CUDA cudaConfigureCall function.
FunctionDecl *cudaConfigureCallDecl;
- TypeSourceInfo NullTypeSourceInfo;
-
/// \brief Keeps track of all declaration attributes.
///
/// Since so few decls have attrs, we keep them in a hash map instead of
@@ -384,6 +391,10 @@ private:
/// this ASTContext object.
LangOptions &LangOpts;
+ /// \brief Blacklist object that is used by sanitizers to decide which
+ /// entities should not be instrumented.
+ std::unique_ptr<SanitizerBlacklist> SanitizerBL;
+
/// \brief The allocator used to create AST objects.
///
/// AST objects are never destructed; rather, all memory associated with the
@@ -453,11 +464,12 @@ public:
/// 'NodeT' can be one of Decl, Stmt, Type, TypeLoc,
/// NestedNameSpecifier or NestedNameSpecifierLoc.
template <typename NodeT>
- ParentVector getParents(const NodeT &Node) {
+ ArrayRef<ast_type_traits::DynTypedNode> getParents(const NodeT &Node) {
return getParents(ast_type_traits::DynTypedNode::create(Node));
}
- ParentVector getParents(const ast_type_traits::DynTypedNode &Node);
+ ArrayRef<ast_type_traits::DynTypedNode>
+ getParents(const ast_type_traits::DynTypedNode &Node);
const clang::PrintingPolicy &getPrintingPolicy() const {
return PrintingPolicy;
@@ -508,6 +520,10 @@ public:
const LangOptions& getLangOpts() const { return LangOpts; }
+ const SanitizerBlacklist &getSanitizerBlacklist() const {
+ return *SanitizerBL;
+ }
+
DiagnosticsEngine &getDiagnostics() const;
FullSourceLoc getFullLoc(SourceLocation Loc) const {
@@ -912,6 +928,12 @@ public:
/// \brief Change the result type of a function type once it is deduced.
void adjustDeducedFunctionResultType(FunctionDecl *FD, QualType ResultType);
+ /// \brief Change the exception specification on a function once it is
+ /// delay-parsed, instantiated, or computed.
+ void adjustExceptionSpec(FunctionDecl *FD,
+ const FunctionProtoType::ExceptionSpecInfo &ESI,
+ bool AsWritten = false);
+
/// \brief Return the uniqued reference to the type for a complex
/// number with the specified element type.
QualType getComplexType(QualType T) const;
@@ -1371,7 +1393,8 @@ public:
///
/// If \p Field is specified then record field names are also encoded.
void getObjCEncodingForType(QualType T, std::string &S,
- const FieldDecl *Field=nullptr) const;
+ const FieldDecl *Field=nullptr,
+ QualType *NotEncodedT=nullptr) const;
/// \brief Emit the Objective-C property type encoding for the given
/// type \p T into \p S.
@@ -1581,7 +1604,7 @@ public:
private:
CanQualType getFromTargetType(unsigned Type) const;
- std::pair<uint64_t, unsigned> getTypeInfoImpl(const Type *T) const;
+ TypeInfo getTypeInfoImpl(const Type *T) const;
//===--------------------------------------------------------------------===//
// Type Predicates.
@@ -1614,18 +1637,12 @@ public:
const llvm::fltSemantics &getFloatTypeSemantics(QualType T) const;
/// \brief Get the size and alignment of the specified complete type in bits.
- std::pair<uint64_t, unsigned> getTypeInfo(const Type *T) const;
- std::pair<uint64_t, unsigned> getTypeInfo(QualType T) const {
- return getTypeInfo(T.getTypePtr());
- }
+ TypeInfo getTypeInfo(const Type *T) const;
+ TypeInfo getTypeInfo(QualType T) const { return getTypeInfo(T.getTypePtr()); }
/// \brief Return the size of the specified (complete) type \p T, in bits.
- uint64_t getTypeSize(QualType T) const {
- return getTypeInfo(T).first;
- }
- uint64_t getTypeSize(const Type *T) const {
- return getTypeInfo(T).first;
- }
+ uint64_t getTypeSize(QualType T) const { return getTypeInfo(T).Width; }
+ uint64_t getTypeSize(const Type *T) const { return getTypeInfo(T).Width; }
/// \brief Return the size of the character type, in bits.
uint64_t getCharWidth() const {
@@ -1645,12 +1662,8 @@ public:
/// \brief Return the ABI-specified alignment of a (complete) type \p T, in
/// bits.
- unsigned getTypeAlign(QualType T) const {
- return getTypeInfo(T).second;
- }
- unsigned getTypeAlign(const Type *T) const {
- return getTypeInfo(T).second;
- }
+ unsigned getTypeAlign(QualType T) const { return getTypeInfo(T).Align; }
+ unsigned getTypeAlign(const Type *T) const { return getTypeInfo(T).Align; }
/// \brief Return the ABI-specified alignment of a (complete) type \p T, in
/// characters.
@@ -1664,6 +1677,11 @@ public:
std::pair<CharUnits, CharUnits> getTypeInfoInChars(const Type *T) const;
std::pair<CharUnits, CharUnits> getTypeInfoInChars(QualType T) const;
+ /// \brief Determine if the alignment the type has was required using an
+ /// alignment attribute.
+ bool isAlignmentRequired(const Type *T) const;
+ bool isAlignmentRequired(QualType T) const;
+
/// \brief Return the "preferred" alignment of the specified type \p T for
/// the current target, in bits.
///
@@ -2153,8 +2171,6 @@ public:
getTrivialTypeSourceInfo(QualType T,
SourceLocation Loc = SourceLocation()) const;
- TypeSourceInfo *getNullTypeSourceInfo() { return &NullTypeSourceInfo; }
-
/// \brief Add a deallocation callback that will be invoked when the
/// ASTContext is destroyed.
///
@@ -2272,12 +2288,14 @@ private:
bool StructField = false,
bool EncodeBlockParameters = false,
bool EncodeClassNames = false,
- bool EncodePointerToObjCTypedef = false) const;
+ bool EncodePointerToObjCTypedef = false,
+ QualType *NotEncodedT=nullptr) const;
// Adds the encoding of the structure's members.
void getObjCEncodingForStructureImpl(RecordDecl *RD, std::string &S,
const FieldDecl *Field,
- bool includeVBases = true) const;
+ bool includeVBases = true,
+ QualType *NotEncodedT=nullptr) const;
public:
// Adds the encoding of a method parameter or return type.
void getObjCEncodingForMethodParameter(Decl::ObjCDeclQualifier QT,
@@ -2312,6 +2330,31 @@ private:
std::unique_ptr<ParentMap> AllParents;
std::unique_ptr<VTableContextBase> VTContext;
+
+public:
+ enum PragmaSectionFlag : unsigned {
+ PSF_None = 0,
+ PSF_Read = 0x1,
+ PSF_Write = 0x2,
+ PSF_Execute = 0x4,
+ PSF_Implicit = 0x8,
+ PSF_Invalid = 0x80000000U,
+ };
+
+ struct SectionInfo {
+ DeclaratorDecl *Decl;
+ SourceLocation PragmaSectionLocation;
+ int SectionFlags;
+ SectionInfo() {}
+ SectionInfo(DeclaratorDecl *Decl,
+ SourceLocation PragmaSectionLocation,
+ int SectionFlags)
+ : Decl(Decl),
+ PragmaSectionLocation(PragmaSectionLocation),
+ SectionFlags(SectionFlags) {}
+ };
+
+ llvm::StringMap<SectionInfo> SectionInfos;
};
/// \brief Utility function for constructing a nullary selector.
@@ -2349,9 +2392,9 @@ static inline Selector GetUnarySelector(StringRef name, ASTContext& Ctx) {
/// // Specific alignment
/// IntegerLiteral *Ex2 = new (Context, 4) IntegerLiteral(arguments);
/// @endcode
-/// Please note that you cannot use delete on the pointer; it must be
-/// deallocated using an explicit destructor call followed by
-/// @c Context.Deallocate(Ptr).
+/// Memory allocated through this placement new operator does not need to be
+/// explicitly freed, as ASTContext will free all of this memory when it gets
+/// destroyed. Please note that you cannot use delete on the pointer.
///
/// @param Bytes The number of bytes to allocate. Calculated by the compiler.
/// @param C The ASTContext that provides the allocator.
@@ -2386,9 +2429,9 @@ inline void operator delete(void *Ptr, const clang::ASTContext &C, size_t) {
/// // Specific alignment
/// char *data = new (Context, 4) char[10];
/// @endcode
-/// Please note that you cannot use delete on the pointer; it must be
-/// deallocated using an explicit destructor call followed by
-/// @c Context.Deallocate(Ptr).
+/// Memory allocated through this placement new[] operator does not need to be
+/// explicitly freed, as ASTContext will free all of this memory when it gets
+/// destroyed. Please note that you cannot use delete on the pointer.
///
/// @param Bytes The number of bytes to allocate. Calculated by the compiler.
/// @param C The ASTContext that provides the allocator.
diff --git a/include/clang/AST/ASTDiagnostic.h b/include/clang/AST/ASTDiagnostic.h
index 484ca4cb8632..27c85e65f2c1 100644
--- a/include/clang/AST/ASTDiagnostic.h
+++ b/include/clang/AST/ASTDiagnostic.h
@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_DIAGNOSTICAST_H
-#define LLVM_CLANG_DIAGNOSTICAST_H
+#ifndef LLVM_CLANG_AST_ASTDIAGNOSTIC_H
+#define LLVM_CLANG_AST_ASTDIAGNOSTIC_H
#include "clang/Basic/Diagnostic.h"
diff --git a/include/clang/AST/ASTFwd.h b/include/clang/AST/ASTFwd.h
index 4f3279874b16..003d489c1ca4 100644
--- a/include/clang/AST/ASTFwd.h
+++ b/include/clang/AST/ASTFwd.h
@@ -12,6 +12,9 @@
///
//===-------------------------------------------------------------===//
+#ifndef LLVM_CLANG_AST_ASTFWD_H
+#define LLVM_CLANG_AST_ASTFWD_H
+
namespace clang {
class Decl;
@@ -26,3 +29,5 @@ class Type;
class CXXCtorInitializer;
} // end namespace clang
+
+#endif
diff --git a/include/clang/AST/ASTLambda.h b/include/clang/AST/ASTLambda.h
index 9af016b13d45..69df2d8c0113 100644
--- a/include/clang/AST/ASTLambda.h
+++ b/include/clang/AST/ASTLambda.h
@@ -13,8 +13,8 @@
///
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_AST_LAMBDA_H
-#define LLVM_CLANG_AST_LAMBDA_H
+#ifndef LLVM_CLANG_AST_ASTLAMBDA_H
+#define LLVM_CLANG_AST_ASTLAMBDA_H
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclTemplate.h"
@@ -77,4 +77,4 @@ inline DeclContext *getLambdaAwareParentOfDeclContext(DeclContext *DC) {
} // clang
-#endif // LLVM_CLANG_AST_LAMBDA_H
+#endif
diff --git a/include/clang/AST/ASTMutationListener.h b/include/clang/AST/ASTMutationListener.h
index a89bfed53fbd..48eb6292772c 100644
--- a/include/clang/AST/ASTMutationListener.h
+++ b/include/clang/AST/ASTMutationListener.h
@@ -102,6 +102,12 @@ public:
/// \param D the declaration marked used
virtual void DeclarationMarkedUsed(const Decl *D) {}
+ /// \brief A declaration is marked as OpenMP threadprivate which was not
+ /// previously marked as threadprivate.
+ ///
+ /// \param D the declaration marked OpenMP threadprivate.
+ virtual void DeclarationMarkedOpenMPThreadPrivate(const Decl *D) {}
+
// NOTE: If new methods are added they should also be added to
// MultiplexASTMutationListener.
};
diff --git a/include/clang/AST/ASTTypeTraits.h b/include/clang/AST/ASTTypeTraits.h
index 0e06e26e6d80..dc3c34f28d94 100644
--- a/include/clang/AST/ASTTypeTraits.h
+++ b/include/clang/AST/ASTTypeTraits.h
@@ -13,8 +13,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_AST_AST_TYPE_TRAITS_H
-#define LLVM_CLANG_AST_AST_TYPE_TRAITS_H
+#ifndef LLVM_CLANG_AST_ASTTYPETRAITS_H
+#define LLVM_CLANG_AST_ASTTYPETRAITS_H
#include "clang/AST/ASTFwd.h"
#include "clang/AST/Decl.h"
@@ -23,6 +23,7 @@
#include "clang/AST/TemplateBase.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/Support/AlignOf.h"
namespace llvm {
@@ -53,9 +54,19 @@ public:
return ASTNodeKind(KindToKindId<T>::Id);
}
+ /// \{
+ /// \brief Construct an identifier for the dynamic type of the node
+ static ASTNodeKind getFromNode(const Decl &D);
+ static ASTNodeKind getFromNode(const Stmt &S);
+ static ASTNodeKind getFromNode(const Type &T);
+ /// \}
+
/// \brief Returns \c true if \c this and \c Other represent the same kind.
bool isSame(ASTNodeKind Other) const;
+ /// \brief Returns \c true only for the default \c ASTNodeKind()
+ bool isNone() const { return KindId == NKI_None; }
+
/// \brief Returns \c true if \c this is a base kind of (or same as) \c Other.
/// \param Distance If non-null, used to return the distance between \c this
/// and \c Other in the class hierarchy.
@@ -69,6 +80,32 @@ public:
return KindId < Other.KindId;
}
+ /// \brief Return the most derived type between \p Kind1 and \p Kind2.
+ ///
+ /// Return ASTNodeKind() if they are not related.
+ static ASTNodeKind getMostDerivedType(ASTNodeKind Kind1, ASTNodeKind Kind2);
+
+ /// \brief Return the most derived common ancestor between Kind1 and Kind2.
+ ///
+ /// Return ASTNodeKind() if they are not related.
+ static ASTNodeKind getMostDerivedCommonAncestor(ASTNodeKind Kind1,
+ ASTNodeKind Kind2);
+
+ /// \brief Hooks for using ASTNodeKind as a key in a DenseMap.
+ struct DenseMapInfo {
+ // ASTNodeKind() is a good empty key because it is represented as a 0.
+ static inline ASTNodeKind getEmptyKey() { return ASTNodeKind(); }
+ // NKI_NumberOfKinds is not a valid value, so it is good for a
+ // tombstone key.
+ static inline ASTNodeKind getTombstoneKey() {
+ return ASTNodeKind(NKI_NumberOfKinds);
+ }
+ static unsigned getHashValue(const ASTNodeKind &Val) { return Val.KindId; }
+ static bool isEqual(const ASTNodeKind &LHS, const ASTNodeKind &RHS) {
+ return LHS.KindId == RHS.KindId;
+ }
+ };
+
private:
/// \brief Kind ids.
///
@@ -108,6 +145,8 @@ private:
template <class T> struct KindToKindId {
static const NodeKindId Id = NKI_None;
};
+ template <class T>
+ struct KindToKindId<const T> : KindToKindId<T> {};
/// \brief Per kind info.
struct KindInfo {
@@ -184,12 +223,22 @@ public:
return BaseConverter<T>::get(NodeKind, Storage.buffer);
}
+ /// \brief Retrieve the stored node as type \c T.
+ ///
+ /// Similar to \c get(), but asserts that the type is what we are expecting.
+ template <typename T>
+ const T &getUnchecked() const {
+ return BaseConverter<T>::getUnchecked(NodeKind, Storage.buffer);
+ }
+
+ ASTNodeKind getNodeKind() const { return NodeKind; }
+
/// \brief Returns a pointer that identifies the stored AST node.
///
/// Note that this is not supported by all AST nodes. For AST nodes
/// that don't have a pointer-defined identity inside the AST, this
/// method returns NULL.
- const void *getMemoizationData() const;
+ const void *getMemoizationData() const { return MemoizationData; }
/// \brief Prints the node to the given output stream.
void print(llvm::raw_ostream &OS, const PrintingPolicy &PP) const;
@@ -212,14 +261,15 @@ public:
return getMemoizationData() < Other.getMemoizationData();
}
bool operator==(const DynTypedNode &Other) const {
- if (!NodeKind.isBaseOf(Other.NodeKind) &&
- !Other.NodeKind.isBaseOf(NodeKind))
+ // DynTypedNode::create() stores the exact kind of the node in NodeKind.
+ // If they contain the same node, their NodeKind must be the same.
+ if (!NodeKind.isSame(Other.NodeKind))
return false;
// FIXME: Implement for other types.
- if (ASTNodeKind::getFromNodeKind<QualType>().isBaseOf(NodeKind)) {
- return *get<QualType>() == *Other.get<QualType>();
- }
+ if (ASTNodeKind::getFromNodeKind<QualType>().isSame(NodeKind))
+ return getUnchecked<QualType>() == Other.getUnchecked<QualType>();
+
assert(getMemoizationData() && Other.getMemoizationData());
return getMemoizationData() == Other.getMemoizationData();
}
@@ -235,13 +285,18 @@ private:
/// \brief Converter that uses dyn_cast<T> from a stored BaseT*.
template <typename T, typename BaseT> struct DynCastPtrConverter {
static const T *get(ASTNodeKind NodeKind, const char Storage[]) {
- if (ASTNodeKind::getFromNodeKind<BaseT>().isBaseOf(NodeKind))
- return dyn_cast<T>(*reinterpret_cast<BaseT *const *>(Storage));
+ if (ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind))
+ return cast<T>(*reinterpret_cast<BaseT *const *>(Storage));
return nullptr;
}
+ static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) {
+ assert(ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind));
+ return *cast<T>(*reinterpret_cast<BaseT *const *>(Storage));
+ }
static DynTypedNode create(const BaseT &Node) {
DynTypedNode Result;
- Result.NodeKind = ASTNodeKind::getFromNodeKind<T>();
+ Result.NodeKind = ASTNodeKind::getFromNode(Node);
+ Result.MemoizationData = &Node;
new (Result.Storage.buffer) const BaseT * (&Node);
return Result;
}
@@ -254,9 +309,14 @@ private:
return *reinterpret_cast<T *const *>(Storage);
return nullptr;
}
+ static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) {
+ assert(ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind));
+ return **reinterpret_cast<T *const *>(Storage);
+ }
static DynTypedNode create(const T &Node) {
DynTypedNode Result;
Result.NodeKind = ASTNodeKind::getFromNodeKind<T>();
+ Result.MemoizationData = &Node;
new (Result.Storage.buffer) const T * (&Node);
return Result;
}
@@ -269,15 +329,21 @@ private:
return reinterpret_cast<const T *>(Storage);
return nullptr;
}
+ static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) {
+ assert(ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind));
+ return *reinterpret_cast<const T *>(Storage);
+ }
static DynTypedNode create(const T &Node) {
DynTypedNode Result;
Result.NodeKind = ASTNodeKind::getFromNodeKind<T>();
+ Result.MemoizationData = nullptr;
new (Result.Storage.buffer) T(Node);
return Result;
}
};
ASTNodeKind NodeKind;
+ const void *MemoizationData;
/// \brief Stores the data of the node.
///
@@ -345,20 +411,15 @@ template <typename T, typename EnablerT> struct DynTypedNode::BaseConverter {
}
};
-inline const void *DynTypedNode::getMemoizationData() const {
- if (ASTNodeKind::getFromNodeKind<Decl>().isBaseOf(NodeKind)) {
- return BaseConverter<Decl>::get(NodeKind, Storage.buffer);
- } else if (ASTNodeKind::getFromNodeKind<Stmt>().isBaseOf(NodeKind)) {
- return BaseConverter<Stmt>::get(NodeKind, Storage.buffer);
- } else if (ASTNodeKind::getFromNodeKind<Type>().isBaseOf(NodeKind)) {
- return BaseConverter<Type>::get(NodeKind, Storage.buffer);
- } else if (ASTNodeKind::getFromNodeKind<NestedNameSpecifier>().isBaseOf(NodeKind)) {
- return BaseConverter<NestedNameSpecifier>::get(NodeKind, Storage.buffer);
- }
- return nullptr;
-}
-
} // end namespace ast_type_traits
} // end namespace clang
-#endif // LLVM_CLANG_AST_AST_TYPE_TRAITS_H
+namespace llvm {
+
+template <>
+struct DenseMapInfo<clang::ast_type_traits::ASTNodeKind>
+ : clang::ast_type_traits::ASTNodeKind::DenseMapInfo {};
+
+} // end namespace llvm
+
+#endif
diff --git a/include/clang/AST/ASTVector.h b/include/clang/AST/ASTVector.h
index d92167e95992..6ec054582e26 100644
--- a/include/clang/AST/ASTVector.h
+++ b/include/clang/AST/ASTVector.h
@@ -15,8 +15,8 @@
// FIXME: Most of this is copy-and-paste from BumpVector.h and SmallVector.h.
// We can refactor this core logic into something common.
-#ifndef LLVM_CLANG_AST_VECTOR
-#define LLVM_CLANG_AST_VECTOR
+#ifndef LLVM_CLANG_AST_ASTVECTOR_H
+#define LLVM_CLANG_AST_ASTVECTOR_H
#include "clang/AST/AttrIterator.h"
#include "llvm/ADT/PointerIntPair.h"
@@ -236,14 +236,14 @@ public:
iterator insert(const ASTContext &C, iterator I, size_type NumToInsert,
const T &Elt) {
- if (I == this->end()) { // Important special case for empty vector.
- append(C, NumToInsert, Elt);
- return this->end()-1;
- }
-
// Convert iterator to elt# to avoid invalidating iterator when we reserve()
size_t InsertElt = I - this->begin();
+ if (I == this->end()) { // Important special case for empty vector.
+ append(C, NumToInsert, Elt);
+ return this->begin() + InsertElt;
+ }
+
// Ensure there is enough space.
reserve(C, static_cast<unsigned>(this->size() + NumToInsert));
@@ -284,14 +284,15 @@ public:
template<typename ItTy>
iterator insert(const ASTContext &C, iterator I, ItTy From, ItTy To) {
- if (I == this->end()) { // Important special case for empty vector.
+ // Convert iterator to elt# to avoid invalidating iterator when we reserve()
+ size_t InsertElt = I - this->begin();
+
+ if (I == this->end()) { // Important special case for empty vector.
append(C, From, To);
- return this->end()-1;
+ return this->begin() + InsertElt;
}
size_t NumToInsert = std::distance(From, To);
- // Convert iterator to elt# to avoid invalidating iterator when we reserve()
- size_t InsertElt = I - this->begin();
// Ensure there is enough space.
reserve(C, static_cast<unsigned>(this->size() + NumToInsert));
diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h
index fc4881619bce..787843e64f56 100644
--- a/include/clang/AST/Attr.h
+++ b/include/clang/AST/Attr.h
@@ -16,6 +16,7 @@
#include "clang/AST/AttrIterator.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
#include "clang/AST/Type.h"
#include "clang/Basic/AttrKinds.h"
#include "clang/Basic/LLVM.h"
diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h
index 7cccef69ddf8..aa3c84682983 100644
--- a/include/clang/AST/CanonicalType.h
+++ b/include/clang/AST/CanonicalType.h
@@ -12,8 +12,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_AST_CANONICAL_TYPE_H
-#define LLVM_CLANG_AST_CANONICAL_TYPE_H
+#ifndef LLVM_CLANG_AST_CANONICALTYPE_H
+#define LLVM_CLANG_AST_CANONICALTYPE_H
#include "clang/AST/Type.h"
#include "llvm/Support/Casting.h"
@@ -736,4 +736,4 @@ CanTypeIterator<InputIterator>::operator->() const {
}
-#endif // LLVM_CLANG_AST_CANONICAL_TYPE_H
+#endif
diff --git a/include/clang/AST/Comment.h b/include/clang/AST/Comment.h
index e18fe9ab86a0..94470cbf305f 100644
--- a/include/clang/AST/Comment.h
+++ b/include/clang/AST/Comment.h
@@ -96,9 +96,10 @@ protected:
unsigned : NumInlineContentCommentBits;
unsigned RenderKind : 2;
- unsigned CommandID : 8;
+ unsigned CommandID : CommandInfo::NumCommandIDBits;
};
- enum { NumInlineCommandCommentBits = NumInlineContentCommentBits + 10 };
+ enum { NumInlineCommandCommentBits = NumInlineContentCommentBits + 2 +
+ CommandInfo::NumCommandIDBits };
class HTMLTagCommentBitfields {
friend class HTMLTagComment;
@@ -139,13 +140,14 @@ protected:
unsigned : NumCommentBits;
- unsigned CommandID : 8;
+ unsigned CommandID : CommandInfo::NumCommandIDBits;
/// Describes the syntax that was used in a documentation command.
/// Contains values from CommandMarkerKind enum.
unsigned CommandMarker : 1;
};
- enum { NumBlockCommandCommentBits = NumCommentBits + 9 };
+ enum { NumBlockCommandCommentBits = NumCommentBits +
+ CommandInfo::NumCommandIDBits + 1 };
class ParamCommandCommentBitfields {
friend class ParamCommandComment;
diff --git a/include/clang/AST/CommentBriefParser.h b/include/clang/AST/CommentBriefParser.h
index 5d508860635d..be5b8eeb80c3 100644
--- a/include/clang/AST/CommentBriefParser.h
+++ b/include/clang/AST/CommentBriefParser.h
@@ -12,8 +12,8 @@
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_AST_BRIEF_COMMENT_PARSER_H
-#define LLVM_CLANG_AST_BRIEF_COMMENT_PARSER_H
+#ifndef LLVM_CLANG_AST_COMMENTBRIEFPARSER_H
+#define LLVM_CLANG_AST_COMMENTBRIEFPARSER_H
#include "clang/AST/CommentLexer.h"
diff --git a/include/clang/AST/CommentCommandTraits.h b/include/clang/AST/CommentCommandTraits.h
index dde7a1442fe1..ec6d83c03021 100644
--- a/include/clang/AST/CommentCommandTraits.h
+++ b/include/clang/AST/CommentCommandTraits.h
@@ -13,8 +13,8 @@
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_AST_COMMENT_COMMAND_TRAITS_H
-#define LLVM_CLANG_AST_COMMENT_COMMAND_TRAITS_H
+#ifndef LLVM_CLANG_AST_COMMENTCOMMANDTRAITS_H
+#define LLVM_CLANG_AST_COMMENTCOMMANDTRAITS_H
#include "clang/Basic/CommentOptions.h"
#include "clang/Basic/LLVM.h"
@@ -40,7 +40,11 @@ struct CommandInfo {
/// Name of the command that ends the verbatim block.
const char *EndCommandName;
- unsigned ID : 8;
+ /// DRY definition of the number of bits used for a command ID.
+ enum { NumCommandIDBits = 20 };
+
+ /// The ID of the command.
+ unsigned ID : NumCommandIDBits;
/// Number of word-like arguments for a given block command, except for
/// \\param and \\tparam commands -- these have special argument parsers.
diff --git a/include/clang/AST/CommentDiagnostic.h b/include/clang/AST/CommentDiagnostic.h
index 312da065ff59..f3a209bf6e7c 100644
--- a/include/clang/AST/CommentDiagnostic.h
+++ b/include/clang/AST/CommentDiagnostic.h
@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_COMMENTDIAGNOSTIC_H
-#define LLVM_CLANG_COMMENTDIAGNOSTIC_H
+#ifndef LLVM_CLANG_AST_COMMENTDIAGNOSTIC_H
+#define LLVM_CLANG_AST_COMMENTDIAGNOSTIC_H
#include "clang/Basic/Diagnostic.h"
diff --git a/include/clang/AST/CommentLexer.h b/include/clang/AST/CommentLexer.h
index a6e3ed89b27e..d995df921282 100644
--- a/include/clang/AST/CommentLexer.h
+++ b/include/clang/AST/CommentLexer.h
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_AST_COMMENT_LEXER_H
-#define LLVM_CLANG_AST_COMMENT_LEXER_H
+#ifndef LLVM_CLANG_AST_COMMENTLEXER_H
+#define LLVM_CLANG_AST_COMMENTLEXER_H
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceManager.h"
diff --git a/include/clang/AST/CommentParser.h b/include/clang/AST/CommentParser.h
index 7e008131d205..2c444f0dc3a6 100644
--- a/include/clang/AST/CommentParser.h
+++ b/include/clang/AST/CommentParser.h
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_AST_COMMENT_PARSER_H
-#define LLVM_CLANG_AST_COMMENT_PARSER_H
+#ifndef LLVM_CLANG_AST_COMMENTPARSER_H
+#define LLVM_CLANG_AST_COMMENTPARSER_H
#include "clang/AST/Comment.h"
#include "clang/AST/CommentLexer.h"
diff --git a/include/clang/AST/CommentSema.h b/include/clang/AST/CommentSema.h
index 027c3b929df6..4ae6fe0c613d 100644
--- a/include/clang/AST/CommentSema.h
+++ b/include/clang/AST/CommentSema.h
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_AST_COMMENT_SEMA_H
-#define LLVM_CLANG_AST_COMMENT_SEMA_H
+#ifndef LLVM_CLANG_AST_COMMENTSEMA_H
+#define LLVM_CLANG_AST_COMMENTSEMA_H
#include "clang/AST/Comment.h"
#include "clang/Basic/Diagnostic.h"
@@ -85,7 +85,7 @@ public:
std::uninitialized_copy(Source.begin(), Source.end(), Mem);
return llvm::makeArrayRef(Mem, Size);
}
- return ArrayRef<T>();
+ return None;
}
ParagraphComment *actOnParagraphComment(
diff --git a/include/clang/AST/DataRecursiveASTVisitor.h b/include/clang/AST/DataRecursiveASTVisitor.h
index 9ef008717b1b..c0526e1cfd45 100644
--- a/include/clang/AST/DataRecursiveASTVisitor.h
+++ b/include/clang/AST/DataRecursiveASTVisitor.h
@@ -424,6 +424,7 @@ private:
bool TraverseFunctionHelper(FunctionDecl *D);
bool TraverseVarHelper(VarDecl *D);
bool TraverseOMPExecutableDirective(OMPExecutableDirective *S);
+ bool TraverseOMPLoopDirective(OMPLoopDirective *S);
bool TraverseOMPClause(OMPClause *C);
#define OPENMP_CLAUSE(Name, Class) bool Visit##Class(Class *C);
#include "clang/Basic/OpenMPKinds.def"
@@ -623,6 +624,7 @@ bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifier(
case NestedNameSpecifier::Namespace:
case NestedNameSpecifier::NamespaceAlias:
case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::Super:
return true;
case NestedNameSpecifier::TypeSpec:
@@ -647,6 +649,7 @@ bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifierLoc(
case NestedNameSpecifier::Namespace:
case NestedNameSpecifier::NamespaceAlias:
case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::Super:
return true;
case NestedNameSpecifier::TypeSpec:
@@ -875,6 +878,9 @@ DEF_TRAVERSE_TYPE(FunctionProtoType, {
for (const auto &E : T->exceptions()) {
TRY_TO(TraverseType(E));
}
+
+ if (Expr *NE = T->getNoexceptExpr())
+ TRY_TO(TraverseStmt(NE));
})
DEF_TRAVERSE_TYPE(UnresolvedUsingType, {})
@@ -1083,6 +1089,9 @@ DEF_TRAVERSE_TYPELOC(FunctionProtoType, {
for (const auto &E : T->exceptions()) {
TRY_TO(TraverseType(E));
}
+
+ if (Expr *NE = T->getNoexceptExpr())
+ TRY_TO(TraverseStmt(NE));
})
DEF_TRAVERSE_TYPELOC(UnresolvedUsingType, {})
@@ -2122,21 +2131,29 @@ bool RecursiveASTVisitor<Derived>::TraverseLambdaExpr(LambdaExpr *S) {
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()));
+ TypeLoc TL = S->getCallOperator()->getTypeSourceInfo()->getTypeLoc();
+ FunctionProtoTypeLoc Proto = TL.castAs<FunctionProtoTypeLoc>();
+
+ if (S->hasExplicitParameters() && S->hasExplicitResultType()) {
+ // Visit the whole type.
+ TRY_TO(TraverseTypeLoc(TL));
+ } else {
+ if (S->hasExplicitParameters()) {
+ // Visit parameters.
+ for (unsigned I = 0, N = Proto.getNumParams(); I != N; ++I) {
+ TRY_TO(TraverseDecl(Proto.getParam(I)));
}
+ } else if (S->hasExplicitResultType()) {
+ TRY_TO(TraverseTypeLoc(Proto.getReturnLoc()));
+ }
+
+ auto *T = Proto.getTypePtr();
+ for (const auto &E : T->exceptions()) {
+ TRY_TO(TraverseType(E));
}
+
+ if (Expr *NE = T->getNoexceptExpr())
+ TRY_TO(TraverseStmt(NE));
}
TRY_TO(TraverseLambdaBody(S));
@@ -2237,6 +2254,7 @@ DEF_TRAVERSE_STMT(CapturedStmt, { TRY_TO(TraverseDecl(S->getCapturedDecl())); })
DEF_TRAVERSE_STMT(CXXOperatorCallExpr, {})
DEF_TRAVERSE_STMT(OpaqueValueExpr, {})
+DEF_TRAVERSE_STMT(TypoExpr, {})
DEF_TRAVERSE_STMT(CUDAKernelCallExpr, {})
// These operators (all of them) do not need any action except
@@ -2253,6 +2271,7 @@ DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmPackExpr, {})
DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmExpr, {})
DEF_TRAVERSE_STMT(FunctionParmPackExpr, {})
DEF_TRAVERSE_STMT(MaterializeTemporaryExpr, {})
+DEF_TRAVERSE_STMT(CXXFoldExpr, {})
DEF_TRAVERSE_STMT(AtomicExpr, {})
// These literals (all of them) do not need any action.
@@ -2279,6 +2298,12 @@ bool RecursiveASTVisitor<Derived>::TraverseOMPExecutableDirective(
return true;
}
+template <typename Derived>
+bool
+RecursiveASTVisitor<Derived>::TraverseOMPLoopDirective(OMPLoopDirective *S) {
+ return TraverseOMPExecutableDirective(S);
+}
+
DEF_TRAVERSE_STMT(OMPParallelDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
@@ -2288,6 +2313,9 @@ DEF_TRAVERSE_STMT(OMPSimdDirective,
DEF_TRAVERSE_STMT(OMPForDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
+DEF_TRAVERSE_STMT(OMPForSimdDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
DEF_TRAVERSE_STMT(OMPSectionsDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
@@ -2308,6 +2336,9 @@ DEF_TRAVERSE_STMT(OMPCriticalDirective, {
DEF_TRAVERSE_STMT(OMPParallelForDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
+DEF_TRAVERSE_STMT(OMPParallelForSimdDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
DEF_TRAVERSE_STMT(OMPParallelSectionsDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
@@ -2326,6 +2357,18 @@ DEF_TRAVERSE_STMT(OMPTaskwaitDirective,
DEF_TRAVERSE_STMT(OMPFlushDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
+DEF_TRAVERSE_STMT(OMPOrderedDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPAtomicDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPTargetDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPTeamsDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
// OpenMP clauses.
template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) {
@@ -2415,6 +2458,31 @@ RecursiveASTVisitor<Derived>::VisitOMPMergeableClause(OMPMergeableClause *) {
}
template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPReadClause(OMPReadClause *) {
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPWriteClause(OMPWriteClause *) {
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPUpdateClause(OMPUpdateClause *) {
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPCaptureClause(OMPCaptureClause *) {
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPSeqCstClause(OMPSeqCstClause *) {
+ return true;
+}
+
+template <typename Derived>
template <typename T>
bool RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) {
for (auto *E : Node->varlists()) {
@@ -2426,6 +2494,9 @@ bool RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) {
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPPrivateClause(OMPPrivateClause *C) {
TRY_TO(VisitOMPClauseList(C));
+ for (auto *E : C->private_copies()) {
+ TRY_TO(TraverseStmt(E));
+ }
return true;
}
@@ -2433,6 +2504,12 @@ template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPFirstprivateClause(
OMPFirstprivateClause *C) {
TRY_TO(VisitOMPClauseList(C));
+ for (auto *E : C->private_copies()) {
+ TRY_TO(TraverseStmt(E));
+ }
+ for (auto *E : C->inits()) {
+ TRY_TO(TraverseStmt(E));
+ }
return true;
}
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index ce8b8b7dbcd6..a39888f9e1f0 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -43,6 +43,7 @@ class Stmt;
class StringLiteral;
class TemplateArgumentList;
class TemplateParameterList;
+class TypeAliasTemplateDecl;
class TypeLoc;
class UnresolvedSetImpl;
class VarTemplateDecl;
@@ -67,6 +68,9 @@ public:
/// \brief Return the TypeLoc wrapper for the type source info.
TypeLoc getTypeLoc() const; // implemented in TypeLoc.h
+
+ /// \brief Override the type stored in this TypeSourceInfo. Use with caution!
+ void overrideType(QualType T) { Ty = T; }
};
/// TranslationUnitDecl - The top declaration context.
@@ -288,6 +292,8 @@ public:
return const_cast<NamedDecl*>(this)->getMostRecentDecl();
}
+ ObjCStringFormatFamily getObjCFStringFormattingFamily() const;
+
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K >= firstNamed && K <= lastNamed; }
};
@@ -305,6 +311,8 @@ inline raw_ostream &operator<<(raw_ostream &OS, const NamedDecl &ND) {
class LabelDecl : public NamedDecl {
void anchor() override;
LabelStmt *TheStmt;
+ StringRef MSAsmName;
+ bool MSAsmNameResolved;
/// LocStart - For normal labels, this is the same as the main declaration
/// label, i.e., the location of the identifier; for GNU local labels,
/// this is the location of the __label__ keyword.
@@ -312,7 +320,10 @@ class LabelDecl : public NamedDecl {
LabelDecl(DeclContext *DC, SourceLocation IdentL, IdentifierInfo *II,
LabelStmt *S, SourceLocation StartL)
- : NamedDecl(Label, DC, IdentL, II), TheStmt(S), LocStart(StartL) {}
+ : NamedDecl(Label, DC, IdentL, II),
+ TheStmt(S),
+ MSAsmNameResolved(false),
+ LocStart(StartL) {}
public:
static LabelDecl *Create(ASTContext &C, DeclContext *DC,
@@ -332,6 +343,12 @@ public:
return SourceRange(LocStart, getLocation());
}
+ bool isMSAsmLabel() const { return MSAsmName.size() != 0; }
+ bool isResolvedMSAsmLabel() const { return isMSAsmLabel() && MSAsmNameResolved; }
+ void setMSAsmLabel(StringRef Name);
+ StringRef getMSAsmLabel() const { return MSAsmName; }
+ void setMSAsmLabelResolved() { MSAsmNameResolved = true; }
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == Label; }
@@ -648,8 +665,6 @@ struct EvaluatedStmt {
/// declaration or definition.
class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
public:
- typedef clang::StorageClass StorageClass;
-
/// getStorageClassSpecifierString - Return the string used to
/// specify the storage class \p SC.
///
@@ -891,6 +906,11 @@ public:
return false;
}
+ /// \brief Similar to isLocalVarDecl but also includes parameters.
+ bool isLocalVarDeclOrParm() const {
+ return isLocalVarDecl() || getKind() == Decl::ParmVar;
+ }
+
/// isFunctionOrMethodVarDecl - Similar to isLocalVarDecl, but
/// excludes variables declared in blocks.
bool isFunctionOrMethodVarDecl() const {
@@ -1423,8 +1443,6 @@ private:
class FunctionDecl : public DeclaratorDecl, public DeclContext,
public Redeclarable<FunctionDecl> {
public:
- typedef clang::StorageClass StorageClass;
-
/// \brief The kind of templated function a FunctionDecl can be.
enum TemplatedKind {
TK_NonTemplate,
@@ -1650,7 +1668,7 @@ public:
/// unnecessary AST de-serialization of the body.
Stmt *getBody(const FunctionDecl *&Definition) const;
- Stmt *getBody() const override {
+ Stmt *getBody() const override {
const FunctionDecl* Definition;
return getBody(Definition);
}
@@ -1880,7 +1898,7 @@ public:
return llvm::makeArrayRef(ParamInfo, getNumParams());
}
- const ArrayRef<NamedDecl *> &getDeclsInPrototypeScope() const {
+ ArrayRef<NamedDecl *> getDeclsInPrototypeScope() const {
return DeclsInPrototypeScope;
}
void setDeclsInPrototypeScope(ArrayRef<NamedDecl *> NewDecls);
@@ -2154,17 +2172,41 @@ class FieldDecl : public DeclaratorDecl, public Mergeable<FieldDecl> {
bool Mutable : 1;
mutable unsigned CachedFieldIndex : 31;
- /// \brief An InClassInitStyle value, and either a bit width expression (if
- /// the InClassInitStyle value is ICIS_NoInit), or a pointer to the in-class
- /// initializer for this field (otherwise).
+ /// The kinds of value we can store in InitializerOrBitWidth.
///
- /// We can safely combine these two because in-class initializers are not
- /// permitted for bit-fields.
+ /// Note that this is compatible with InClassInitStyle except for
+ /// ISK_CapturedVLAType.
+ enum InitStorageKind {
+ /// If the pointer is null, there's nothing special. Otherwise,
+ /// this is a bitfield and the pointer is the Expr* storing the
+ /// bit-width.
+ ISK_BitWidthOrNothing = (unsigned) ICIS_NoInit,
+
+ /// The pointer is an (optional due to delayed parsing) Expr*
+ /// holding the copy-initializer.
+ ISK_InClassCopyInit = (unsigned) ICIS_CopyInit,
+
+ /// The pointer is an (optional due to delayed parsing) Expr*
+ /// holding the list-initializer.
+ ISK_InClassListInit = (unsigned) ICIS_ListInit,
+
+ /// The pointer is a VariableArrayType* that's been captured;
+ /// the enclosing context is a lambda or captured statement.
+ ISK_CapturedVLAType,
+ };
+
+ /// \brief Storage for either the bit-width, the in-class
+ /// initializer, or the captured variable length array bound.
+ ///
+ /// We can safely combine these because in-class initializers are
+ /// not permitted for bit-fields, and both are exclusive with VLA
+ /// captures.
///
- /// If the InClassInitStyle is not ICIS_NoInit and the initializer is null,
- /// then this field has an in-class initializer which has not yet been parsed
+ /// If the storage kind is ISK_InClassCopyInit or
+ /// ISK_InClassListInit, but the initializer is null, then this
+ /// field has an in-class initializer which has not yet been parsed
/// and attached.
- llvm::PointerIntPair<Expr *, 2, unsigned> InitializerOrBitWidth;
+ llvm::PointerIntPair<void *, 2, InitStorageKind> InitStorage;
protected:
FieldDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc, IdentifierInfo *Id,
@@ -2172,7 +2214,7 @@ protected:
InClassInitStyle InitStyle)
: DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc),
Mutable(Mutable), CachedFieldIndex(0),
- InitializerOrBitWidth(BW, InitStyle) {
+ InitStorage(BW, (InitStorageKind) InitStyle) {
assert((!BW || InitStyle == ICIS_NoInit) && "got initializer for bitfield");
}
@@ -2192,10 +2234,10 @@ public:
/// isMutable - Determines whether this field is mutable (C++ only).
bool isMutable() const { return Mutable; }
- /// isBitfield - Determines whether this field is a bitfield.
+ /// \brief Determines whether this field is a bitfield.
bool isBitField() const {
- return getInClassInitStyle() == ICIS_NoInit &&
- InitializerOrBitWidth.getPointer();
+ return InitStorage.getInt() == ISK_BitWidthOrNothing &&
+ InitStorage.getPointer() != nullptr;
}
/// @brief Determines whether this is an unnamed bitfield.
@@ -2208,24 +2250,34 @@ public:
bool isAnonymousStructOrUnion() const;
Expr *getBitWidth() const {
- return isBitField() ? InitializerOrBitWidth.getPointer() : nullptr;
+ return isBitField()
+ ? static_cast<Expr *>(InitStorage.getPointer())
+ : nullptr;
}
unsigned getBitWidthValue(const ASTContext &Ctx) const;
/// setBitWidth - Set the bit-field width for this member.
// Note: used by some clients (i.e., do not remove it).
- void setBitWidth(Expr *Width);
+ void setBitWidth(Expr *Width) {
+ assert(InitStorage.getInt() == ISK_BitWidthOrNothing &&
+ InitStorage.getPointer() == nullptr &&
+ "bit width, initializer or captured type already set");
+ InitStorage.setPointerAndInt(Width, ISK_BitWidthOrNothing);
+ }
+
/// removeBitWidth - Remove the bit-field width from this member.
// Note: used by some clients (i.e., do not remove it).
void removeBitWidth() {
assert(isBitField() && "no bitfield width to remove");
- InitializerOrBitWidth.setPointer(nullptr);
+ InitStorage.setPointerAndInt(nullptr, ISK_BitWidthOrNothing);
}
/// getInClassInitStyle - Get the kind of (C++11) in-class initializer which
/// this field has.
InClassInitStyle getInClassInitStyle() const {
- return static_cast<InClassInitStyle>(InitializerOrBitWidth.getInt());
+ InitStorageKind storageKind = InitStorage.getInt();
+ return (storageKind == ISK_CapturedVLAType
+ ? ICIS_NoInit : (InClassInitStyle) storageKind);
}
/// hasInClassInitializer - Determine whether this member has a C++11 in-class
@@ -2233,24 +2285,47 @@ public:
bool hasInClassInitializer() const {
return getInClassInitStyle() != ICIS_NoInit;
}
+
/// getInClassInitializer - Get the C++11 in-class initializer for this
/// member, or null if one has not been set. If a valid declaration has an
/// in-class initializer, but this returns null, then we have not parsed and
/// attached it yet.
Expr *getInClassInitializer() const {
- return hasInClassInitializer() ? InitializerOrBitWidth.getPointer()
- : nullptr;
+ return hasInClassInitializer()
+ ? static_cast<Expr *>(InitStorage.getPointer())
+ : nullptr;
}
+
/// setInClassInitializer - Set the C++11 in-class initializer for this
/// member.
- void setInClassInitializer(Expr *Init);
+ void setInClassInitializer(Expr *Init) {
+ assert(hasInClassInitializer() &&
+ InitStorage.getPointer() == nullptr &&
+ "bit width, initializer or captured type already set");
+ InitStorage.setPointer(Init);
+ }
+
/// removeInClassInitializer - Remove the C++11 in-class initializer from this
/// member.
void removeInClassInitializer() {
assert(hasInClassInitializer() && "no initializer to remove");
- InitializerOrBitWidth.setPointer(nullptr);
- InitializerOrBitWidth.setInt(ICIS_NoInit);
+ InitStorage.setPointerAndInt(nullptr, ISK_BitWidthOrNothing);
+ }
+
+ /// \brief Determine whether this member captures the variable length array
+ /// type.
+ bool hasCapturedVLAType() const {
+ return InitStorage.getInt() == ISK_CapturedVLAType;
+ }
+
+ /// \brief Get the captured variable length array type.
+ const VariableArrayType *getCapturedVLAType() const {
+ return hasCapturedVLAType() ? static_cast<const VariableArrayType *>(
+ InitStorage.getPointer())
+ : nullptr;
}
+ /// \brief Set the captured variable length array type for this field.
+ void setCapturedVLAType(const VariableArrayType *VLAType);
/// getParent - Returns the parent of this field declaration, which
/// is the struct in which this method is defined.
@@ -2492,9 +2567,13 @@ public:
/// TypeAliasDecl - Represents the declaration of a typedef-name via a C++0x
/// alias-declaration.
class TypeAliasDecl : public TypedefNameDecl {
+ /// The template for which this is the pattern, if any.
+ TypeAliasTemplateDecl *Template;
+
TypeAliasDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc, IdentifierInfo *Id, TypeSourceInfo *TInfo)
- : TypedefNameDecl(TypeAlias, C, DC, StartLoc, IdLoc, Id, TInfo) {}
+ : TypedefNameDecl(TypeAlias, C, DC, StartLoc, IdLoc, Id, TInfo),
+ Template(nullptr) {}
public:
static TypeAliasDecl *Create(ASTContext &C, DeclContext *DC,
@@ -2504,6 +2583,9 @@ public:
SourceRange getSourceRange() const override LLVM_READONLY;
+ TypeAliasTemplateDecl *getDescribedAliasTemplate() const { return Template; }
+ void setDescribedAliasTemplate(TypeAliasTemplateDecl *TAT) { Template = TAT; }
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == TypeAlias; }
@@ -2647,7 +2729,7 @@ public:
}
/// isThisDeclarationADefinition() - Return true if this declaration
- /// is a completion definintion of the type. Provided for consistency.
+ /// is a completion definition of the type. Provided for consistency.
bool isThisDeclarationADefinition() const {
return isCompleteDefinition();
}
@@ -3136,6 +3218,17 @@ public:
/// \endcode
bool isInjectedClassName() const;
+ /// \brief Determine whether this record is a class describing a lambda
+ /// function object.
+ bool isLambda() const;
+
+ /// \brief Determine whether this record is a record for captured variables in
+ /// CapturedStmt construct.
+ bool isCapturedRecord() const;
+ /// \brief Mark the record as a record for captured variables in CapturedStmt
+ /// construct.
+ void setCapturedRecord();
+
/// getDefinition - Returns the RecordDecl that actually defines
/// this struct/union/class. When determining whether or not a
/// struct/union/class is completely defined, one should use this
@@ -3181,6 +3274,15 @@ public:
/// commandline option.
bool isMsStruct(const ASTContext &C) const;
+ /// \brief Whether we are allowed to insert extra padding between fields.
+ /// These padding are added to help AddressSanitizer detect
+ /// intra-object-overflow bugs.
+ bool mayInsertExtraPadding(bool EmitRemark = false) const;
+
+ /// Finds the first data member which has a name.
+ /// nullptr is returned if no named data member exists.
+ const FieldDecl *findFirstNamedDataMember() const;
+
private:
/// \brief Deserialize just the fields.
void LoadFieldsFromExternalStorage() const;
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index 607ca4ec27c6..984ab13df426 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -48,6 +48,7 @@ class ObjCInterfaceDecl;
class ObjCMethodDecl;
class ObjCProtocolDecl;
struct PrintingPolicy;
+class RecordDecl;
class Stmt;
class StoredDeclsMap;
class TranslationUnitDecl;
@@ -515,9 +516,13 @@ public:
/// indicating the declaration is used.
void markUsed(ASTContext &C);
- /// \brief Whether this declaration was referenced.
+ /// \brief Whether any declaration of this entity was referenced.
bool isReferenced() const;
+ /// \brief Whether this declaration was referenced. This should not be relied
+ /// upon for anything other than debugging.
+ bool isThisDeclarationReferenced() const { return Referenced; }
+
void setReferenced(bool R = true) { Referenced = R; }
/// \brief Whether this declaration is a top-level declaration (function,
@@ -675,9 +680,9 @@ public:
return const_cast<Decl*>(this)->getLexicalDeclContext();
}
- virtual bool isOutOfLine() const {
- return getLexicalDeclContext() != getDeclContext();
- }
+ /// Determine whether this declaration is declared out of line (outside its
+ /// semantic context).
+ virtual bool isOutOfLine() const;
/// setDeclContext - Set both the semantic and lexical DeclContext
/// to DC.
@@ -1234,6 +1239,12 @@ public:
return const_cast<DeclContext *>(this)->getEnclosingNamespaceContext();
}
+ /// \brief Retrieve the outermost lexically enclosing record context.
+ RecordDecl *getOuterLexicalRecordContext();
+ const RecordDecl *getOuterLexicalRecordContext() const {
+ return const_cast<DeclContext *>(this)->getOuterLexicalRecordContext();
+ }
+
/// \brief Test if this context is part of the enclosing namespace set of
/// the context NS, as defined in C++0x [namespace.def]p9. If either context
/// isn't a namespace, this is equivalent to Equals().
@@ -1642,7 +1653,7 @@ public:
void dumpDeclContext() const;
void dumpLookups() const;
- void dumpLookups(llvm::raw_ostream &OS) const;
+ void dumpLookups(llvm::raw_ostream &OS, bool DumpDecls = false) const;
private:
void reconcileExternalVisibleStorage() const;
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
index 72fad7c28e49..027b41e27da3 100644
--- a/include/clang/AST/DeclCXX.h
+++ b/include/clang/AST/DeclCXX.h
@@ -538,6 +538,12 @@ class CXXRecordDecl : public RecordDecl {
ManglingNumber(0), ContextDecl(nullptr), Captures(nullptr),
MethodTyInfo(Info) {
IsLambda = true;
+
+ // C++11 [expr.prim.lambda]p3:
+ // This class type is neither an aggregate nor a literal type.
+ Aggregate = false;
+ PlainOldData = false;
+ HasNonLiteralTypeFieldsOrBases = true;
}
/// \brief Whether this lambda is known to be dependent, even if its
@@ -820,7 +826,11 @@ public:
/// This value is used for lazy creation of default constructors.
bool needsImplicitDefaultConstructor() const {
return !data().UserDeclaredConstructor &&
- !(data().DeclaredSpecialMembers & SMF_DefaultConstructor);
+ !(data().DeclaredSpecialMembers & SMF_DefaultConstructor) &&
+ // C++14 [expr.prim.lambda]p20:
+ // The closure type associated with a lambda-expression has no
+ // default constructor.
+ !isLambda();
}
/// \brief Determine whether this class has any user-declared constructors.
@@ -1371,6 +1381,15 @@ public:
/// \brief Set the kind of specialization or template instantiation this is.
void setTemplateSpecializationKind(TemplateSpecializationKind TSK);
+ /// \brief Retrieve the record declaration from which this record could be
+ /// instantiated. Returns null if this class is not a template instantiation.
+ const CXXRecordDecl *getTemplateInstantiationPattern() const;
+
+ CXXRecordDecl *getTemplateInstantiationPattern() {
+ return const_cast<CXXRecordDecl *>(const_cast<const CXXRecordDecl *>(this)
+ ->getTemplateInstantiationPattern());
+ }
+
/// \brief Returns the destructor decl for this class.
CXXDestructorDecl *getDestructor() const;
@@ -2104,8 +2123,8 @@ public:
}
ArrayRef<VarDecl *> getArrayIndexes() {
assert(getNumArrayIndices() != 0 && "Getting indexes for non-array init");
- return ArrayRef<VarDecl *>(reinterpret_cast<VarDecl **>(this + 1),
- getNumArrayIndices());
+ return llvm::makeArrayRef(reinterpret_cast<VarDecl **>(this + 1),
+ getNumArrayIndices());
}
/// \brief Get the initializer.
@@ -2636,7 +2655,8 @@ public:
/// \code
/// namespace Foo = Bar;
/// \endcode
-class NamespaceAliasDecl : public NamedDecl {
+class NamespaceAliasDecl : public NamedDecl,
+ public Redeclarable<NamespaceAliasDecl> {
void anchor() override;
/// \brief The location of the \c namespace keyword.
@@ -2654,17 +2674,47 @@ class NamespaceAliasDecl : public NamedDecl {
/// a NamespaceAliasDecl.
NamedDecl *Namespace;
- NamespaceAliasDecl(DeclContext *DC, SourceLocation NamespaceLoc,
- SourceLocation AliasLoc, IdentifierInfo *Alias,
- NestedNameSpecifierLoc QualifierLoc,
+ NamespaceAliasDecl(ASTContext &C, DeclContext *DC,
+ SourceLocation NamespaceLoc, SourceLocation AliasLoc,
+ IdentifierInfo *Alias, NestedNameSpecifierLoc QualifierLoc,
SourceLocation IdentLoc, NamedDecl *Namespace)
- : NamedDecl(NamespaceAlias, DC, AliasLoc, Alias),
- NamespaceLoc(NamespaceLoc), IdentLoc(IdentLoc),
- QualifierLoc(QualifierLoc), Namespace(Namespace) { }
+ : NamedDecl(NamespaceAlias, DC, AliasLoc, Alias), redeclarable_base(C),
+ NamespaceLoc(NamespaceLoc), IdentLoc(IdentLoc),
+ QualifierLoc(QualifierLoc), Namespace(Namespace) {}
+
+ typedef Redeclarable<NamespaceAliasDecl> redeclarable_base;
+ NamespaceAliasDecl *getNextRedeclarationImpl() override;
+ NamespaceAliasDecl *getPreviousDeclImpl() override;
+ NamespaceAliasDecl *getMostRecentDeclImpl() override;
friend class ASTDeclReader;
public:
+ static NamespaceAliasDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation NamespaceLoc,
+ SourceLocation AliasLoc,
+ IdentifierInfo *Alias,
+ NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation IdentLoc,
+ NamedDecl *Namespace);
+
+ static NamespaceAliasDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ typedef redeclarable_base::redecl_range redecl_range;
+ typedef redeclarable_base::redecl_iterator redecl_iterator;
+ using redeclarable_base::redecls_begin;
+ using redeclarable_base::redecls_end;
+ using redeclarable_base::redecls;
+ using redeclarable_base::getPreviousDecl;
+ using redeclarable_base::getMostRecentDecl;
+
+ NamespaceAliasDecl *getCanonicalDecl() override {
+ return getFirstDecl();
+ }
+ const NamespaceAliasDecl *getCanonicalDecl() const {
+ return getFirstDecl();
+ }
+
/// \brief Retrieve the nested-name-specifier that qualifies the
/// name of the namespace, with source-location information.
NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
@@ -2701,16 +2751,6 @@ public:
/// may either be a NamespaceDecl or a NamespaceAliasDecl.
NamedDecl *getAliasedNamespace() const { return Namespace; }
- static NamespaceAliasDecl *Create(ASTContext &C, DeclContext *DC,
- SourceLocation NamespaceLoc,
- SourceLocation AliasLoc,
- IdentifierInfo *Alias,
- NestedNameSpecifierLoc QualifierLoc,
- SourceLocation IdentLoc,
- NamedDecl *Namespace);
-
- static NamespaceAliasDecl *CreateDeserialized(ASTContext &C, unsigned ID);
-
SourceRange getSourceRange() const override LLVM_READONLY {
return SourceRange(NamespaceLoc, IdentLoc);
}
@@ -2824,7 +2864,7 @@ public:
/// \code
/// using someNameSpace::someIdentifier;
/// \endcode
-class UsingDecl : public NamedDecl {
+class UsingDecl : public NamedDecl, public Mergeable<UsingDecl> {
void anchor() override;
/// \brief The source location of the 'using' keyword itself.
@@ -2948,6 +2988,10 @@ public:
SourceRange getSourceRange() const override LLVM_READONLY;
+ /// Retrieves the canonical declaration of this declaration.
+ UsingDecl *getCanonicalDecl() override { return getFirstDecl(); }
+ const UsingDecl *getCanonicalDecl() const { return getFirstDecl(); }
+
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == Using; }
@@ -2966,7 +3010,8 @@ public:
/// using Base<T>::foo;
/// };
/// \endcode
-class UnresolvedUsingValueDecl : public ValueDecl {
+class UnresolvedUsingValueDecl : public ValueDecl,
+ public Mergeable<UnresolvedUsingValueDecl> {
void anchor() override;
/// \brief The source location of the 'using' keyword
@@ -3022,6 +3067,14 @@ public:
SourceRange getSourceRange() const override LLVM_READONLY;
+ /// Retrieves the canonical declaration of this declaration.
+ UnresolvedUsingValueDecl *getCanonicalDecl() override {
+ return getFirstDecl();
+ }
+ const UnresolvedUsingValueDecl *getCanonicalDecl() const {
+ return getFirstDecl();
+ }
+
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == UnresolvedUsingValue; }
@@ -3040,7 +3093,9 @@ public:
///
/// The type associated with an unresolved using typename decl is
/// currently always a typename type.
-class UnresolvedUsingTypenameDecl : public TypeDecl {
+class UnresolvedUsingTypenameDecl
+ : public TypeDecl,
+ public Mergeable<UnresolvedUsingTypenameDecl> {
void anchor() override;
/// \brief The source location of the 'typename' keyword
@@ -3084,6 +3139,14 @@ public:
static UnresolvedUsingTypenameDecl *
CreateDeserialized(ASTContext &C, unsigned ID);
+ /// Retrieves the canonical declaration of this declaration.
+ UnresolvedUsingTypenameDecl *getCanonicalDecl() override {
+ return getFirstDecl();
+ }
+ const UnresolvedUsingTypenameDecl *getCanonicalDecl() const {
+ return getFirstDecl();
+ }
+
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == UnresolvedUsingTypename; }
};
diff --git a/include/clang/AST/DeclLookups.h b/include/clang/AST/DeclLookups.h
index d2016af89f13..eba2266724fd 100644
--- a/include/clang/AST/DeclLookups.h
+++ b/include/clang/AST/DeclLookups.h
@@ -75,7 +75,10 @@ inline DeclContext::lookups_range DeclContext::lookups() const {
if (StoredDeclsMap *Map = Primary->buildLookup())
return lookups_range(all_lookups_iterator(Map->begin(), Map->end()),
all_lookups_iterator(Map->end(), Map->end()));
- return lookups_range();
+
+ // Synthesize an empty range. This requires that two default constructed
+ // versions of these iterators form a valid empty range.
+ return lookups_range(all_lookups_iterator(), all_lookups_iterator());
}
inline DeclContext::all_lookups_iterator DeclContext::lookups_begin() const {
@@ -91,7 +94,10 @@ inline DeclContext::lookups_range DeclContext::noload_lookups() const {
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();
+
+ // Synthesize an empty range. This requires that two default constructed
+ // versions of these iterators form a valid empty range.
+ return lookups_range(all_lookups_iterator(), all_lookups_iterator());
}
inline
diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h
index db3b0849382a..55d4b0f16953 100644
--- a/include/clang/AST/DeclObjC.h
+++ b/include/clang/AST/DeclObjC.h
@@ -329,6 +329,7 @@ public:
QualType getReturnType() const { return MethodDeclType; }
void setReturnType(QualType T) { MethodDeclType = T; }
+ SourceRange getReturnTypeSourceRange() const;
/// \brief Determine the type of an expression that sends a message to this
/// function.
@@ -378,8 +379,7 @@ public:
/// ignored.
void setMethodParams(ASTContext &C,
ArrayRef<ParmVarDecl*> Params,
- ArrayRef<SourceLocation> SelLocs =
- ArrayRef<SourceLocation>());
+ ArrayRef<SourceLocation> SelLocs = llvm::None);
// Iterator access to parameter types.
typedef std::const_mem_fun_t<QualType, ParmVarDecl> deref_fun;
@@ -591,7 +591,8 @@ public:
bool HasUserDeclaredSetterMethod(const ObjCPropertyDecl *P) const;
ObjCIvarDecl *getIvarDecl(IdentifierInfo *Id) const;
- ObjCPropertyDecl *FindPropertyDeclaration(IdentifierInfo *PropertyId) const;
+ ObjCPropertyDecl *
+ FindPropertyDeclaration(const IdentifierInfo *PropertyId) const;
typedef llvm::DenseMap<IdentifierInfo*, ObjCPropertyDecl*> PropertyMap;
@@ -2354,7 +2355,7 @@ public:
/// Lookup a property by name in the specified DeclContext.
static ObjCPropertyDecl *findPropertyDecl(const DeclContext *DC,
- IdentifierInfo *propertyID);
+ const IdentifierInfo *propertyID);
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == ObjCProperty; }
diff --git a/include/clang/AST/DeclOpenMP.h b/include/clang/AST/DeclOpenMP.h
index 1b329dcd0052..7f0616f1e603 100644
--- a/include/clang/AST/DeclOpenMP.h
+++ b/include/clang/AST/DeclOpenMP.h
@@ -12,13 +12,14 @@
///
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_AST_OPENMP_H
-#define LLVM_CLANG_AST_OPENMP_H
+#ifndef LLVM_CLANG_AST_DECLOPENMP_H
+#define LLVM_CLANG_AST_DECLOPENMP_H
#include "clang/AST/DeclBase.h"
#include "llvm/ADT/ArrayRef.h"
namespace clang {
+class Expr;
/// \brief This represents '#pragma omp threadprivate ...' directive.
/// For example, in the following, both 'a' and 'A::b' are threadprivate:
@@ -42,9 +43,8 @@ class OMPThreadPrivateDecl : public Decl {
Decl(DK, DC, L), NumVars(0) { }
ArrayRef<const Expr *> getVars() const {
- return ArrayRef<const Expr *>(
- reinterpret_cast<const Expr * const *>(this + 1),
- NumVars);
+ return llvm::makeArrayRef(reinterpret_cast<const Expr * const *>(this + 1),
+ NumVars);
}
MutableArrayRef<Expr *> getVars() {
diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h
index 980a06e35b70..9283d2dc4350 100644
--- a/include/clang/AST/DeclTemplate.h
+++ b/include/clang/AST/DeclTemplate.h
@@ -87,10 +87,10 @@ public:
unsigned size() const { return NumParams; }
ArrayRef<NamedDecl*> asArray() {
- return ArrayRef<NamedDecl*>(begin(), size());
+ return llvm::makeArrayRef(begin(), end());
}
ArrayRef<const NamedDecl*> asArray() const {
- return ArrayRef<const NamedDecl*>(begin(), size());
+ return llvm::makeArrayRef(begin(), size());
}
NamedDecl* getParam(unsigned Idx) {
@@ -204,7 +204,7 @@ public:
/// \brief Produce this as an array ref.
ArrayRef<TemplateArgument> asArray() const {
- return ArrayRef<TemplateArgument>(data(), size());
+ return llvm::makeArrayRef(data(), size());
}
/// \brief Retrieve the number of template arguments in this
@@ -236,7 +236,7 @@ protected:
TemplateParams(nullptr) {}
// Construct a template decl with the given name and parameters.
- // Used when there is not templated element (tt-params, alias?).
+ // Used when there is not templated element (tt-params).
TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L,
DeclarationName Name, TemplateParameterList *Params)
: NamedDecl(DK, DC, L, Name), TemplatedDecl(nullptr),
diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h
index 3076b30cd377..49e51e09b830 100644
--- a/include/clang/AST/DeclarationName.h
+++ b/include/clang/AST/DeclarationName.h
@@ -59,6 +59,7 @@ public:
CXXLiteralOperatorName,
CXXUsingDirective
};
+ static const unsigned NumNameKinds = CXXUsingDirective + 1;
private:
/// StoredNameKind - The kind of name that is actually stored in the
diff --git a/include/clang/AST/DependentDiagnostic.h b/include/clang/AST/DependentDiagnostic.h
index 63047ec4db84..8e038c83c989 100644
--- a/include/clang/AST/DependentDiagnostic.h
+++ b/include/clang/AST/DependentDiagnostic.h
@@ -15,8 +15,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_AST_DEPENDENT_DIAGNOSTIC_H
-#define LLVM_CLANG_AST_DEPENDENT_DIAGNOSTIC_H
+#ifndef LLVM_CLANG_AST_DEPENDENTDIAGNOSTIC_H
+#define LLVM_CLANG_AST_DEPENDENTDIAGNOSTIC_H
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclContextInternals.h"
@@ -178,7 +178,8 @@ inline DeclContext::ddiag_range DeclContext::ddiags() const {
= static_cast<DependentStoredDeclsMap*>(getPrimaryContext()->getLookupPtr());
if (!Map)
- return ddiag_range();
+ // Return an empty range using the always-end default constructor.
+ return ddiag_range(ddiag_iterator(), ddiag_iterator());
return ddiag_range(ddiag_iterator(Map->FirstDiagnostic), ddiag_iterator());
}
diff --git a/include/clang/AST/EvaluatedExprVisitor.h b/include/clang/AST/EvaluatedExprVisitor.h
index 12c4fcc49b01..59de104b83f9 100644
--- a/include/clang/AST/EvaluatedExprVisitor.h
+++ b/include/clang/AST/EvaluatedExprVisitor.h
@@ -56,6 +56,17 @@ public:
return this->Visit(E->getChosenSubExpr());
}
+ void VisitGenericSelectionExpr(GenericSelectionExpr *E) {
+ // The controlling expression of a generic selection is not evaluated.
+
+ // Don't visit either child expression if the condition is type-dependent.
+ if (E->isResultDependent())
+ return;
+ // Only the selected subexpression matters; the other subexpressions and the
+ // controlling expression are not evaluated.
+ return this->Visit(E->getResultExpr());
+ }
+
void VisitDesignatedInitExpr(DesignatedInitExpr *E) {
// Only the actual initializer matters; the designators are all constant
// expressions.
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index b4bb0b6b6440..c410f2358bc7 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -45,6 +45,7 @@ namespace clang {
class ObjCPropertyRefExpr;
class OpaqueValueExpr;
class ParmVarDecl;
+ class StringLiteral;
class TargetInfo;
class ValueDecl;
@@ -124,8 +125,7 @@ public:
QualType getType() const { return TR; }
void setType(QualType t) {
// In C++, the type of an expression is always adjusted so that it
- // will not have reference type an expression will never have
- // reference type (C++ [expr]p6). Use
+ // will not have reference type (C++ [expr]p6). Use
// QualType::getNonReferenceType() to retrieve the non-reference
// type. Additionally, inspect Expr::isLvalue to determine whether
// an expression that is adjusted in this manner should be
@@ -586,8 +586,13 @@ public:
/// HasSideEffects - This routine returns true for all those expressions
/// which have any effect other than producing a value. Example is a function
- /// call, volatile variable read, or throwing an exception.
- bool HasSideEffects(const ASTContext &Ctx) const;
+ /// call, volatile variable read, or throwing an exception. If
+ /// IncludePossibleEffects is false, this call treats certain expressions with
+ /// potential side effects (such as function call-like expressions,
+ /// instantiation-dependent expressions, or invocations from a macro) as not
+ /// having side effects.
+ bool HasSideEffects(const ASTContext &Ctx,
+ bool IncludePossibleEffects = true) const;
/// \brief Determine whether this expression involves a call to any function
/// that is not trivial.
@@ -886,9 +891,9 @@ public:
/// DeclRefExprBits.HasTemplateKWAndArgsInfo:
/// Specifies when this declaration reference expression has an explicit
/// C++ template keyword and/or template argument list.
-/// DeclRefExprBits.RefersToEnclosingLocal
+/// DeclRefExprBits.RefersToEnclosingVariableOrCapture
/// Specifies when this declaration reference expression (validly)
-/// refers to a local variable from a different function.
+/// refers to an enclosed local or a captured variable.
class DeclRefExpr : public Expr {
/// \brief The declaration that we are referencing.
ValueDecl *D;
@@ -933,7 +938,7 @@ class DeclRefExpr : public Expr {
DeclRefExpr(const ASTContext &Ctx,
NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc,
- ValueDecl *D, bool refersToEnclosingLocal,
+ ValueDecl *D, bool RefersToEnlosingVariableOrCapture,
const DeclarationNameInfo &NameInfo,
NamedDecl *FoundD,
const TemplateArgumentListInfo *TemplateArgs,
@@ -948,7 +953,7 @@ class DeclRefExpr : public Expr {
void computeDependence(const ASTContext &C);
public:
- DeclRefExpr(ValueDecl *D, bool refersToEnclosingLocal, QualType T,
+ DeclRefExpr(ValueDecl *D, bool RefersToEnclosingVariableOrCapture, QualType T,
ExprValueKind VK, SourceLocation L,
const DeclarationNameLoc &LocInfo = DeclarationNameLoc())
: Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false, false),
@@ -957,20 +962,22 @@ public:
DeclRefExprBits.HasTemplateKWAndArgsInfo = 0;
DeclRefExprBits.HasFoundDecl = 0;
DeclRefExprBits.HadMultipleCandidates = 0;
- DeclRefExprBits.RefersToEnclosingLocal = refersToEnclosingLocal;
+ DeclRefExprBits.RefersToEnclosingVariableOrCapture =
+ RefersToEnclosingVariableOrCapture;
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 = nullptr,
+ SourceLocation TemplateKWLoc, ValueDecl *D,
+ bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc,
+ QualType T, ExprValueKind VK, NamedDecl *FoundD = nullptr,
const TemplateArgumentListInfo *TemplateArgs = nullptr);
static DeclRefExpr *
Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc,
- SourceLocation TemplateKWLoc, ValueDecl *D, bool isEnclosingLocal,
+ SourceLocation TemplateKWLoc, ValueDecl *D,
+ bool RefersToEnclosingVariableOrCapture,
const DeclarationNameInfo &NameInfo, QualType T, ExprValueKind VK,
NamedDecl *FoundD = nullptr,
const TemplateArgumentListInfo *TemplateArgs = nullptr);
@@ -1144,10 +1151,10 @@ public:
DeclRefExprBits.HadMultipleCandidates = V;
}
- /// Does this DeclRefExpr refer to a local declaration from an
- /// enclosing function scope?
- bool refersToEnclosingLocal() const {
- return DeclRefExprBits.RefersToEnclosingLocal;
+ /// \brief Does this DeclRefExpr refer to an enclosing local or a captured
+ /// variable?
+ bool refersToEnclosingVariableOrCapture() const {
+ return DeclRefExprBits.RefersToEnclosingVariableOrCapture;
}
static bool classof(const Stmt *T) {
@@ -1161,7 +1168,7 @@ public:
friend class ASTStmtWriter;
};
-/// PredefinedExpr - [C99 6.4.2.2] - A predefined identifier such as __func__.
+/// \brief [C99 6.4.2.2] - A predefined identifier such as __func__.
class PredefinedExpr : public Expr {
public:
enum IdentType {
@@ -1171,7 +1178,7 @@ public:
FuncDName,
FuncSig,
PrettyFunction,
- /// PrettyFunctionNoVirtual - The same as PrettyFunction, except that the
+ /// \brief The same as PrettyFunction, except that the
/// 'virtual' keyword is omitted for virtual member functions.
PrettyFunctionNoVirtual
};
@@ -1179,24 +1186,27 @@ public:
private:
SourceLocation Loc;
IdentType Type;
+ Stmt *FnName;
+
public:
- PredefinedExpr(SourceLocation l, QualType type, IdentType IT)
- : Expr(PredefinedExprClass, type, VK_LValue, OK_Ordinary,
- type->isDependentType(), type->isDependentType(),
- type->isInstantiationDependentType(),
- /*ContainsUnexpandedParameterPack=*/false),
- Loc(l), Type(IT) {}
+ PredefinedExpr(SourceLocation L, QualType FNTy, IdentType IT,
+ StringLiteral *SL);
/// \brief Construct an empty predefined expression.
explicit PredefinedExpr(EmptyShell Empty)
- : Expr(PredefinedExprClass, Empty) { }
+ : Expr(PredefinedExprClass, Empty), Loc(), Type(Func), FnName(nullptr) {}
IdentType getIdentType() const { return Type; }
- void setIdentType(IdentType IT) { Type = IT; }
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
+ StringLiteral *getFunctionName();
+ const StringLiteral *getFunctionName() const {
+ return const_cast<PredefinedExpr *>(this)->getFunctionName();
+ }
+
+ static StringRef getIdentTypeName(IdentType IT);
static std::string ComputeName(IdentType IT, const Decl *CurrentDecl);
SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
@@ -1207,7 +1217,9 @@ public:
}
// Iterators
- child_range children() { return child_range(); }
+ child_range children() { return child_range(&FnName, &FnName + 1); }
+
+ friend class ASTStmtReader;
};
/// \brief Used by IntegerLiteral/FloatingLiteral to store the numeric without
@@ -2212,11 +2224,11 @@ public:
/// getArg - Return the specified argument.
Expr *getArg(unsigned Arg) {
assert(Arg < NumArgs && "Arg access out of range!");
- return cast<Expr>(SubExprs[Arg+getNumPreArgs()+PREARGS_START]);
+ return cast_or_null<Expr>(SubExprs[Arg + getNumPreArgs() + PREARGS_START]);
}
const Expr *getArg(unsigned Arg) const {
assert(Arg < NumArgs && "Arg access out of range!");
- return cast<Expr>(SubExprs[Arg+getNumPreArgs()+PREARGS_START]);
+ return cast_or_null<Expr>(SubExprs[Arg + getNumPreArgs() + PREARGS_START]);
}
/// setArg - Set the specified argument.
@@ -2256,8 +2268,8 @@ public:
/// interface. This provides efficient reverse iteration of the
/// subexpressions. This is currently used for CFG construction.
ArrayRef<Stmt*> getRawSubExprs() {
- return ArrayRef<Stmt*>(SubExprs,
- getNumPreArgs() + PREARGS_START + getNumArgs());
+ return llvm::makeArrayRef(SubExprs,
+ getNumPreArgs() + PREARGS_START + getNumArgs());
}
/// getNumCommas - Return the number of commas that must have been present in
@@ -2653,9 +2665,6 @@ public:
/// representation in the source code (ExplicitCastExpr's derived
/// classes).
class CastExpr : public Expr {
-public:
- typedef clang::CastKind CastKind;
-
private:
Stmt *Op;
@@ -2673,20 +2682,23 @@ private:
}
protected:
- CastExpr(StmtClass SC, QualType ty, ExprValueKind VK,
- const CastKind kind, Expr *op, unsigned BasePathSize) :
- Expr(SC, ty, VK, OK_Ordinary,
- // Cast expressions are type-dependent if the type is
- // dependent (C++ [temp.dep.expr]p3).
- ty->isDependentType(),
- // Cast expressions are value-dependent if the type is
- // dependent or if the subexpression is value-dependent.
- ty->isDependentType() || (op && op->isValueDependent()),
- (ty->isInstantiationDependentType() ||
- (op && op->isInstantiationDependent())),
- (ty->containsUnexpandedParameterPack() ||
- (op && op->containsUnexpandedParameterPack()))),
- Op(op) {
+ CastExpr(StmtClass SC, QualType ty, ExprValueKind VK, const CastKind kind,
+ Expr *op, unsigned BasePathSize)
+ : Expr(SC, ty, VK, OK_Ordinary,
+ // Cast expressions are type-dependent if the type is
+ // dependent (C++ [temp.dep.expr]p3).
+ ty->isDependentType(),
+ // Cast expressions are value-dependent if the type is
+ // dependent or if the subexpression is value-dependent.
+ ty->isDependentType() || (op && op->isValueDependent()),
+ (ty->isInstantiationDependentType() ||
+ (op && op->isInstantiationDependent())),
+ // An implicit cast expression doesn't (lexically) contain an
+ // unexpanded pack, even if its target type does.
+ ((SC != ImplicitCastExprClass &&
+ ty->containsUnexpandedParameterPack()) ||
+ (op && op->containsUnexpandedParameterPack()))),
+ Op(op) {
assert(kind != CK_Invalid && "creating cast with invalid cast kind");
CastExprBits.Kind = kind;
setBasePathSize(BasePathSize);
@@ -4841,6 +4853,24 @@ public:
return child_range(SubExprs, SubExprs+NumSubExprs);
}
};
+
+/// TypoExpr - Internal placeholder for expressions where typo correction
+/// still needs to be performed and/or an error diagnostic emitted.
+class TypoExpr : public Expr {
+public:
+ TypoExpr(QualType T)
+ : Expr(TypoExprClass, T, VK_LValue, OK_Ordinary,
+ /*isTypeDependent*/ true,
+ /*isValueDependent*/ true,
+ /*isInstantiationDependent*/ true,
+ /*containsUnexpandedParameterPack*/ false) {
+ assert(T->isDependentType() && "TypoExpr given a non-dependent type");
+ }
+
+ child_range children() { return child_range(); }
+ SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); }
+ SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); }
+};
} // end namespace clang
#endif
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h
index 3a43d6dac140..176817823ea9 100644
--- a/include/clang/AST/ExprCXX.h
+++ b/include/clang/AST/ExprCXX.h
@@ -17,10 +17,10 @@
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
+#include "clang/AST/LambdaCapture.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/UnresolvedSet.h"
#include "clang/Basic/ExpressionTraits.h"
-#include "clang/AST/LambdaCapture.h"
#include "clang/Basic/TypeTraits.h"
#include "llvm/Support/Compiler.h"
@@ -967,8 +967,14 @@ public:
const FieldDecl *getField() const { return Field; }
/// \brief Get the initialization expression that will be used.
- const Expr *getExpr() const { return Field->getInClassInitializer(); }
- Expr *getExpr() { return Field->getInClassInitializer(); }
+ const Expr *getExpr() const {
+ assert(Field->getInClassInitializer() && "initializer hasn't been parsed");
+ return Field->getInClassInitializer();
+ }
+ Expr *getExpr() {
+ assert(Field->getInClassInitializer() && "initializer hasn't been parsed");
+ return Field->getInClassInitializer();
+ }
SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
@@ -1165,6 +1171,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 Args; }
arg_iterator arg_end() { return Args + NumArgs; }
@@ -1569,12 +1582,12 @@ class CXXScalarValueInitExpr : public Expr {
public:
/// \brief Create an explicitly-written scalar-value initialization
/// expression.
- CXXScalarValueInitExpr(QualType Type,
- TypeSourceInfo *TypeInfo,
- SourceLocation rParenLoc ) :
- Expr(CXXScalarValueInitExprClass, Type, VK_RValue, OK_Ordinary,
- false, false, Type->isInstantiationDependentType(), false),
- RParenLoc(rParenLoc), TypeInfo(TypeInfo) {}
+ CXXScalarValueInitExpr(QualType Type, TypeSourceInfo *TypeInfo,
+ SourceLocation rParenLoc)
+ : Expr(CXXScalarValueInitExprClass, Type, VK_RValue, OK_Ordinary,
+ false, false, Type->isInstantiationDependentType(),
+ Type->containsUnexpandedParameterPack()),
+ RParenLoc(rParenLoc), TypeInfo(TypeInfo) {}
explicit CXXScalarValueInitExpr(EmptyShell Shell)
: Expr(CXXScalarValueInitExprClass, Shell) { }
@@ -2113,7 +2126,7 @@ public:
/// \brief Retrieve the argument types.
ArrayRef<TypeSourceInfo *> getArgs() const {
- return ArrayRef<TypeSourceInfo *>(getTypeSourceInfos(), getNumArgs());
+ return llvm::makeArrayRef(getTypeSourceInfos(), getNumArgs());
}
typedef TypeSourceInfo **arg_iterator;
@@ -2767,7 +2780,7 @@ public:
ArrayRef<CleanupObject> objects);
ArrayRef<CleanupObject> getObjects() const {
- return ArrayRef<CleanupObject>(getObjectsBuffer(), getNumObjects());
+ return llvm::makeArrayRef(getObjectsBuffer(), getNumObjects());
}
unsigned getNumObjects() const { return ExprWithCleanupsBits.NumObjects; }
@@ -2902,8 +2915,9 @@ public:
SourceLocation getLocStart() const LLVM_READONLY;
SourceLocation getLocEnd() const LLVM_READONLY {
- assert(RParenLoc.isValid() || NumArgs == 1);
- return RParenLoc.isValid() ? RParenLoc : getArg(0)->getLocEnd();
+ if (!RParenLoc.isValid() && NumArgs > 0)
+ return getArg(NumArgs - 1)->getLocEnd();
+ return RParenLoc;
}
static bool classof(const Stmt *T) {
@@ -3811,6 +3825,69 @@ public:
}
};
+/// \brief Represents a folding of a pack over an operator.
+///
+/// This expression is always dependent and represents a pack expansion of the
+/// forms:
+///
+/// ( expr op ... )
+/// ( ... op expr )
+/// ( expr op ... op expr )
+class CXXFoldExpr : public Expr {
+ SourceLocation LParenLoc;
+ SourceLocation EllipsisLoc;
+ SourceLocation RParenLoc;
+ Stmt *SubExprs[2];
+ BinaryOperatorKind Opcode;
+
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+public:
+ CXXFoldExpr(QualType T, SourceLocation LParenLoc, Expr *LHS,
+ BinaryOperatorKind Opcode, SourceLocation EllipsisLoc, Expr *RHS,
+ SourceLocation RParenLoc)
+ : Expr(CXXFoldExprClass, T, VK_RValue, OK_Ordinary,
+ /*Dependent*/ true, true, true,
+ /*ContainsUnexpandedParameterPack*/ false),
+ LParenLoc(LParenLoc), EllipsisLoc(EllipsisLoc), RParenLoc(RParenLoc),
+ Opcode(Opcode) {
+ SubExprs[0] = LHS;
+ SubExprs[1] = RHS;
+ }
+ CXXFoldExpr(EmptyShell Empty) : Expr(CXXFoldExprClass, Empty) {}
+
+ Expr *getLHS() const { return static_cast<Expr*>(SubExprs[0]); }
+ Expr *getRHS() const { return static_cast<Expr*>(SubExprs[1]); }
+
+ /// Does this produce a right-associated sequence of operators?
+ bool isRightFold() const {
+ return getLHS() && getLHS()->containsUnexpandedParameterPack();
+ }
+ /// Does this produce a left-associated sequence of operators?
+ bool isLeftFold() const { return !isRightFold(); }
+ /// Get the pattern, that is, the operand that contains an unexpanded pack.
+ Expr *getPattern() const { return isLeftFold() ? getRHS() : getLHS(); }
+ /// Get the operand that doesn't contain a pack, for a binary fold.
+ Expr *getInit() const { return isLeftFold() ? getLHS() : getRHS(); }
+
+ SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
+ BinaryOperatorKind getOperator() const { return Opcode; }
+
+ SourceLocation getLocStart() const LLVM_READONLY {
+ return LParenLoc;
+ }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ return RParenLoc;
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXFoldExprClass;
+ }
+
+ // Iterators
+ child_range children() { return child_range(SubExprs, SubExprs + 2); }
+};
+
} // end namespace clang
#endif
diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h
index 817c0cc43131..f296e8f71d30 100644
--- a/include/clang/AST/ExprObjC.h
+++ b/include/clang/AST/ExprObjC.h
@@ -124,6 +124,15 @@ public:
// Iterators
child_range children() { return child_range(&SubExpr, &SubExpr+1); }
+
+ typedef ConstExprIterator const_arg_iterator;
+
+ const_arg_iterator arg_begin() const {
+ return reinterpret_cast<Stmt const * const*>(&SubExpr);
+ }
+ const_arg_iterator arg_end() const {
+ return reinterpret_cast<Stmt const * const*>(&SubExpr + 1);
+ }
friend class ASTStmtReader;
};
diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h
index 1e8eff38d3ec..ff1d180ee8c6 100644
--- a/include/clang/AST/ExternalASTSource.h
+++ b/include/clang/AST/ExternalASTSource.h
@@ -11,8 +11,8 @@
// construction of AST nodes from some external source.
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H
-#define LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H
+#ifndef LLVM_CLANG_AST_EXTERNALASTSOURCE_H
+#define LLVM_CLANG_AST_EXTERNALASTSOURCE_H
#include "clang/AST/CharUnits.h"
#include "clang/AST/DeclBase.h"
@@ -650,4 +650,4 @@ typedef LazyOffsetPtr<CXXBaseSpecifier, uint64_t,
} // end namespace clang
-#endif // LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H
+#endif
diff --git a/include/clang/AST/LambdaCapture.h b/include/clang/AST/LambdaCapture.h
index 8633c9796523..a7468a0fd53f 100644
--- a/include/clang/AST/LambdaCapture.h
+++ b/include/clang/AST/LambdaCapture.h
@@ -68,13 +68,23 @@ public:
/// \brief Determine whether this capture handles the C++ \c this
/// pointer.
- bool capturesThis() const { return DeclAndBits.getPointer() == nullptr; }
+ bool capturesThis() const {
+ return (DeclAndBits.getPointer() == nullptr) &&
+ !(DeclAndBits.getInt() & Capture_ByCopy);
+ }
/// \brief Determine whether this capture handles a variable.
bool capturesVariable() const {
return dyn_cast_or_null<VarDecl>(DeclAndBits.getPointer());
}
+ /// \brief Determine whether this captures a variable length array bound
+ /// expression.
+ bool capturesVLAType() const {
+ return (DeclAndBits.getPointer() == nullptr) &&
+ (DeclAndBits.getInt() & Capture_ByCopy);
+ }
+
/// \brief Determine whether this is an init-capture.
bool isInitCapture() const {
return capturesVariable() && getCapturedVar()->isInitCapture();
diff --git a/include/clang/AST/Mangle.h b/include/clang/AST/Mangle.h
index a8d119971b33..cbe08a1a765e 100644
--- a/include/clang/AST/Mangle.h
+++ b/include/clang/AST/Mangle.h
@@ -156,6 +156,11 @@ public:
virtual void mangleItaniumThreadLocalWrapper(const VarDecl *D,
raw_ostream &) = 0;
+ virtual void mangleCXXCtorComdat(const CXXConstructorDecl *D,
+ raw_ostream &) = 0;
+ virtual void mangleCXXDtorComdat(const CXXDestructorDecl *D,
+ raw_ostream &) = 0;
+
static bool classof(const MangleContext *C) {
return C->getKind() == MK_Itanium;
}
diff --git a/include/clang/AST/MangleNumberingContext.h b/include/clang/AST/MangleNumberingContext.h
index 56c995264b32..7a818557fdb7 100644
--- a/include/clang/AST/MangleNumberingContext.h
+++ b/include/clang/AST/MangleNumberingContext.h
@@ -12,8 +12,8 @@
// literals.
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_MANGLENUMBERINGCONTEXT_H
-#define LLVM_CLANG_MANGLENUMBERINGCONTEXT_H
+#ifndef LLVM_CLANG_AST_MANGLENUMBERINGCONTEXT_H
+#define LLVM_CLANG_AST_MANGLENUMBERINGCONTEXT_H
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/DenseMap.h"
@@ -30,23 +30,20 @@ class VarDecl;
/// \brief Keeps track of the mangled names of lambda expressions and block
/// literals within a particular context.
-class MangleNumberingContext
- : public RefCountedBase<MangleNumberingContext> {
- llvm::DenseMap<const Type *, unsigned> ManglingNumbers;
-
+class MangleNumberingContext : public RefCountedBase<MangleNumberingContext> {
public:
virtual ~MangleNumberingContext() {}
/// \brief Retrieve the mangling number of a new lambda expression with the
/// given call operator within this context.
- unsigned getManglingNumber(const CXXMethodDecl *CallOperator);
+ virtual unsigned getManglingNumber(const CXXMethodDecl *CallOperator) = 0;
/// \brief Retrieve the mangling number of a new block literal within this
/// context.
- unsigned getManglingNumber(const BlockDecl *BD);
+ virtual unsigned getManglingNumber(const BlockDecl *BD) = 0;
/// Static locals are numbered by source order.
- unsigned getStaticLocalNumber(const VarDecl *VD);
+ virtual unsigned getStaticLocalNumber(const VarDecl *VD) = 0;
/// \brief Retrieve the mangling number of a static local variable within
/// this context.
@@ -58,6 +55,6 @@ public:
virtual unsigned getManglingNumber(const TagDecl *TD,
unsigned MSLocalManglingNumber) = 0;
};
-
+
} // end namespace clang
#endif
diff --git a/include/clang/AST/NSAPI.h b/include/clang/AST/NSAPI.h
index 0b21b0334812..33fcce2109aa 100644
--- a/include/clang/AST/NSAPI.h
+++ b/include/clang/AST/NSAPI.h
@@ -42,7 +42,8 @@ public:
NSStr_stringWithUTF8String,
NSStr_stringWithCStringEncoding,
NSStr_stringWithCString,
- NSStr_initWithString
+ NSStr_initWithString,
+ NSStr_initWithUTF8String
};
static const unsigned NumNSStringMethods = 5;
@@ -100,8 +101,8 @@ public:
NSDict_objectForKey,
NSMutableDict_setObjectForKey
};
- static const unsigned NumNSDictionaryMethods = 11;
-
+ static const unsigned NumNSDictionaryMethods = 12;
+
/// \brief The Objective-C NSDictionary selectors.
Selector getNSDictionarySelector(NSDictionaryMethodKind MK) const;
@@ -184,6 +185,9 @@ public:
bool isObjCNSIntegerType(QualType T) const;
/// \brief Returns true if \param T is a typedef of "NSUInteger" in objective-c.
bool isObjCNSUIntegerType(QualType T) const;
+ /// \brief Returns one of NSIntegral typedef names if \param T is a typedef
+ /// of that name in objective-c.
+ StringRef GetNSIntegralKind(QualType T) const;
private:
bool isObjCTypedef(QualType T, StringRef name, IdentifierInfo *&II) const;
diff --git a/include/clang/AST/NestedNameSpecifier.h b/include/clang/AST/NestedNameSpecifier.h
index fc719bdc16c3..518f1232fe8f 100644
--- a/include/clang/AST/NestedNameSpecifier.h
+++ b/include/clang/AST/NestedNameSpecifier.h
@@ -22,6 +22,7 @@
namespace clang {
class ASTContext;
+class CXXRecordDecl;
class NamespaceAliasDecl;
class NamespaceDecl;
class IdentifierInfo;
@@ -45,7 +46,7 @@ class NestedNameSpecifier : public llvm::FoldingSetNode {
/// \brief Enumeration describing
enum StoredSpecifierKind {
StoredIdentifier = 0,
- StoredNamespaceOrAlias = 1,
+ StoredDecl = 1,
StoredTypeSpec = 2,
StoredTypeSpecWithTemplate = 3
};
@@ -83,7 +84,10 @@ public:
/// stored as a Type*.
TypeSpecWithTemplate,
/// \brief The global specifier '::'. There is no stored value.
- Global
+ Global,
+ /// \brief Microsoft's '__super' specifier, stored as a CXXRecordDecl* of
+ /// the class it appeared in.
+ Super
};
private:
@@ -143,6 +147,11 @@ public:
/// scope.
static NestedNameSpecifier *GlobalSpecifier(const ASTContext &Context);
+ /// \brief Returns the nested name specifier representing the __super scope
+ /// for the given CXXRecordDecl.
+ static NestedNameSpecifier *SuperSpecifier(const ASTContext &Context,
+ CXXRecordDecl *RD);
+
/// \brief Return the prefix of this nested name specifier.
///
/// The prefix contains all of the parts of the nested name
@@ -172,6 +181,10 @@ public:
/// specifier.
NamespaceAliasDecl *getAsNamespaceAlias() const;
+ /// \brief Retrieve the record declaration stored in this nested name
+ /// specifier.
+ CXXRecordDecl *getAsRecordDecl() const;
+
/// \brief Retrieve the type stored in this nested name specifier.
const Type *getAsType() const {
if (Prefix.getInt() == StoredTypeSpec ||
@@ -421,7 +434,22 @@ public:
/// \brief Turn this (empty) nested-name-specifier into the global
/// nested-name-specifier '::'.
void MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc);
-
+
+ /// \brief Turns this (empty) nested-name-specifier into '__super'
+ /// nested-name-specifier.
+ ///
+ /// \param Context The AST context in which this nested-name-specifier
+ /// resides.
+ ///
+ /// \param RD The declaration of the class in which nested-name-specifier
+ /// appeared.
+ ///
+ /// \param SuperLoc The location of the '__super' keyword.
+ /// name.
+ ///
+ /// \param ColonColonLoc The location of the trailing '::'.
+ void MakeSuper(ASTContext &Context, CXXRecordDecl *RD,
+ SourceLocation SuperLoc, SourceLocation ColonColonLoc);
/// \brief Make a new nested-name-specifier from incomplete source-location
/// information.
///
diff --git a/include/clang/AST/OpenMPClause.h b/include/clang/AST/OpenMPClause.h
index 3345959653a6..0c3002c103e2 100644
--- a/include/clang/AST/OpenMPClause.h
+++ b/include/clang/AST/OpenMPClause.h
@@ -61,7 +61,7 @@ public:
ConstStmtRange children() const {
return const_cast<OMPClause *>(this)->children();
}
- static bool classof(const OMPClause *T) { return true; }
+ static bool classof(const OMPClause *) { return true; }
};
/// \brief This represents clauses with the list of variables like 'private',
@@ -135,10 +135,10 @@ public:
/// \brief Fetches list of all variables in the clause.
ArrayRef<const Expr *> getVarRefs() const {
- return ArrayRef<const Expr *>(
+ return llvm::makeArrayRef(
reinterpret_cast<const Expr *const *>(
reinterpret_cast<const char *>(this) +
- llvm::RoundUpToAlignment(sizeof(T), llvm::alignOf<Expr *>())),
+ llvm::RoundUpToAlignment(sizeof(T), llvm::alignOf<const Expr *>())),
NumVars);
}
};
@@ -770,6 +770,153 @@ public:
StmtRange children() { return StmtRange(); }
};
+/// \brief This represents 'read' clause in the '#pragma omp atomic' directive.
+///
+/// \code
+/// #pragma omp atomic read
+/// \endcode
+/// In this example directive '#pragma omp atomic' has 'read' clause.
+///
+class OMPReadClause : public OMPClause {
+public:
+ /// \brief Build 'read' clause.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPReadClause(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_read, StartLoc, EndLoc) {}
+
+ /// \brief Build an empty clause.
+ ///
+ OMPReadClause() : OMPClause(OMPC_read, SourceLocation(), SourceLocation()) {}
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_read;
+ }
+
+ StmtRange children() { return StmtRange(); }
+};
+
+/// \brief This represents 'write' clause in the '#pragma omp atomic' directive.
+///
+/// \code
+/// #pragma omp atomic write
+/// \endcode
+/// In this example directive '#pragma omp atomic' has 'write' clause.
+///
+class OMPWriteClause : public OMPClause {
+public:
+ /// \brief Build 'write' clause.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPWriteClause(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_write, StartLoc, EndLoc) {}
+
+ /// \brief Build an empty clause.
+ ///
+ OMPWriteClause()
+ : OMPClause(OMPC_write, SourceLocation(), SourceLocation()) {}
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_write;
+ }
+
+ StmtRange children() { return StmtRange(); }
+};
+
+/// \brief This represents 'update' clause in the '#pragma omp atomic'
+/// directive.
+///
+/// \code
+/// #pragma omp atomic update
+/// \endcode
+/// In this example directive '#pragma omp atomic' has 'update' clause.
+///
+class OMPUpdateClause : public OMPClause {
+public:
+ /// \brief Build 'update' clause.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPUpdateClause(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_update, StartLoc, EndLoc) {}
+
+ /// \brief Build an empty clause.
+ ///
+ OMPUpdateClause()
+ : OMPClause(OMPC_update, SourceLocation(), SourceLocation()) {}
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_update;
+ }
+
+ StmtRange children() { return StmtRange(); }
+};
+
+/// \brief This represents 'capture' clause in the '#pragma omp atomic'
+/// directive.
+///
+/// \code
+/// #pragma omp atomic capture
+/// \endcode
+/// In this example directive '#pragma omp atomic' has 'capture' clause.
+///
+class OMPCaptureClause : public OMPClause {
+public:
+ /// \brief Build 'capture' clause.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPCaptureClause(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_capture, StartLoc, EndLoc) {}
+
+ /// \brief Build an empty clause.
+ ///
+ OMPCaptureClause()
+ : OMPClause(OMPC_capture, SourceLocation(), SourceLocation()) {}
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_capture;
+ }
+
+ StmtRange children() { return StmtRange(); }
+};
+
+/// \brief This represents 'seq_cst' clause in the '#pragma omp atomic'
+/// directive.
+///
+/// \code
+/// #pragma omp atomic seq_cst
+/// \endcode
+/// In this example directive '#pragma omp atomic' has 'seq_cst' clause.
+///
+class OMPSeqCstClause : public OMPClause {
+public:
+ /// \brief Build 'seq_cst' clause.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPSeqCstClause(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_seq_cst, StartLoc, EndLoc) {}
+
+ /// \brief Build an empty clause.
+ ///
+ OMPSeqCstClause()
+ : OMPClause(OMPC_seq_cst, SourceLocation(), SourceLocation()) {}
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_seq_cst;
+ }
+
+ StmtRange children() { return StmtRange(); }
+};
+
/// \brief This represents clause 'private' in the '#pragma omp ...' directives.
///
/// \code
@@ -779,6 +926,7 @@ public:
/// with the variables 'a' and 'b'.
///
class OMPPrivateClause : public OMPVarListClause<OMPPrivateClause> {
+ friend class OMPClauseReader;
/// \brief Build clause with number of variables \a N.
///
/// \param StartLoc Starting location of the clause.
@@ -800,6 +948,20 @@ class OMPPrivateClause : public OMPVarListClause<OMPPrivateClause> {
SourceLocation(), SourceLocation(),
N) {}
+ /// \brief Sets the list of references to private copies with initializers for
+ /// new private variables.
+ /// \param VL List of references.
+ void setPrivateCopies(ArrayRef<Expr *> VL);
+
+ /// \brief Gets the list of references to private copies with initializers for
+ /// new private variables.
+ MutableArrayRef<Expr *> getPrivateCopies() {
+ return MutableArrayRef<Expr *>(varlist_end(), varlist_size());
+ }
+ ArrayRef<const Expr *> getPrivateCopies() const {
+ return llvm::makeArrayRef(varlist_end(), varlist_size());
+ }
+
public:
/// \brief Creates clause with a list of variables \a VL.
///
@@ -808,10 +970,12 @@ public:
/// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
/// \param VL List of references to the variables.
+ /// \param PrivateVL List of references to private copies with initializers.
///
static OMPPrivateClause *Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation LParenLoc,
- SourceLocation EndLoc, ArrayRef<Expr *> VL);
+ SourceLocation EndLoc, ArrayRef<Expr *> VL,
+ ArrayRef<Expr *> PrivateVL);
/// \brief Creates an empty clause with the place for \a N variables.
///
/// \param C AST context.
@@ -819,6 +983,21 @@ public:
///
static OMPPrivateClause *CreateEmpty(const ASTContext &C, unsigned N);
+ typedef MutableArrayRef<Expr *>::iterator private_copies_iterator;
+ typedef ArrayRef<const Expr *>::iterator private_copies_const_iterator;
+ typedef llvm::iterator_range<private_copies_iterator> private_copies_range;
+ typedef llvm::iterator_range<private_copies_const_iterator>
+ private_copies_const_range;
+
+ private_copies_range private_copies() {
+ return private_copies_range(getPrivateCopies().begin(),
+ getPrivateCopies().end());
+ }
+ private_copies_const_range private_copies() const {
+ return private_copies_const_range(getPrivateCopies().begin(),
+ getPrivateCopies().end());
+ }
+
StmtRange children() {
return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
reinterpret_cast<Stmt **>(varlist_end()));
@@ -839,6 +1018,8 @@ public:
/// with the variables 'a' and 'b'.
///
class OMPFirstprivateClause : public OMPVarListClause<OMPFirstprivateClause> {
+ friend class OMPClauseReader;
+
/// \brief Build clause with number of variables \a N.
///
/// \param StartLoc Starting location of the clause.
@@ -859,6 +1040,33 @@ class OMPFirstprivateClause : public OMPVarListClause<OMPFirstprivateClause> {
: OMPVarListClause<OMPFirstprivateClause>(
OMPC_firstprivate, SourceLocation(), SourceLocation(),
SourceLocation(), N) {}
+ /// \brief Sets the list of references to private copies with initializers for
+ /// new private variables.
+ /// \param VL List of references.
+ void setPrivateCopies(ArrayRef<Expr *> VL);
+
+ /// \brief Gets the list of references to private copies with initializers for
+ /// new private variables.
+ MutableArrayRef<Expr *> getPrivateCopies() {
+ return MutableArrayRef<Expr *>(varlist_end(), varlist_size());
+ }
+ ArrayRef<const Expr *> getPrivateCopies() const {
+ return llvm::makeArrayRef(varlist_end(), varlist_size());
+ }
+
+ /// \brief Sets the list of references to initializer variables for new
+ /// private variables.
+ /// \param VL List of references.
+ void setInits(ArrayRef<Expr *> VL);
+
+ /// \brief Gets the list of references to initializer variables for new
+ /// private variables.
+ MutableArrayRef<Expr *> getInits() {
+ return MutableArrayRef<Expr *>(getPrivateCopies().end(), varlist_size());
+ }
+ ArrayRef<const Expr *> getInits() const {
+ return llvm::makeArrayRef(getPrivateCopies().end(), varlist_size());
+ }
public:
/// \brief Creates clause with a list of variables \a VL.
@@ -867,11 +1075,16 @@ public:
/// \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 VL List of references to the original variables.
+ /// \param PrivateVL List of references to private copies with initializers.
+ /// \param InitVL List of references to auto generated variables used for
+ /// initialization of a single array element. Used if firstprivate variable is
+ /// of array type.
///
static OMPFirstprivateClause *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
- SourceLocation EndLoc, ArrayRef<Expr *> VL);
+ SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> PrivateVL,
+ ArrayRef<Expr *> InitVL);
/// \brief Creates an empty clause with the place for \a N variables.
///
/// \param C AST context.
@@ -879,6 +1092,33 @@ public:
///
static OMPFirstprivateClause *CreateEmpty(const ASTContext &C, unsigned N);
+ typedef MutableArrayRef<Expr *>::iterator private_copies_iterator;
+ typedef ArrayRef<const Expr *>::iterator private_copies_const_iterator;
+ typedef llvm::iterator_range<private_copies_iterator> private_copies_range;
+ typedef llvm::iterator_range<private_copies_const_iterator>
+ private_copies_const_range;
+
+ private_copies_range private_copies() {
+ return private_copies_range(getPrivateCopies().begin(),
+ getPrivateCopies().end());
+ }
+ private_copies_const_range private_copies() const {
+ return private_copies_const_range(getPrivateCopies().begin(),
+ getPrivateCopies().end());
+ }
+
+ typedef MutableArrayRef<Expr *>::iterator inits_iterator;
+ typedef ArrayRef<const Expr *>::iterator inits_const_iterator;
+ typedef llvm::iterator_range<inits_iterator> inits_range;
+ typedef llvm::iterator_range<inits_const_iterator> inits_const_range;
+
+ inits_range inits() {
+ return inits_range(getInits().begin(), getInits().end());
+ }
+ inits_const_range inits() const {
+ return inits_const_range(getInits().begin(), getInits().end());
+ }
+
StmtRange children() {
return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
reinterpret_cast<Stmt **>(varlist_end()));
@@ -1390,13 +1630,17 @@ public:
}
};
-/// \brief This represents pseudo clause 'flush' for the '#pragma omp flush'
+/// \brief This represents implicit clause 'flush' for the '#pragma omp flush'
/// directive.
+/// This clause does not exist by itself, it can be only as a part of 'omp
+/// flush' directive. This clause is introduced to keep the original structure
+/// of \a OMPExecutableDirective class and its derivatives and to use the
+/// existing infrastructure of clauses with the list of variables.
///
/// \code
/// #pragma omp flush(a,b)
/// \endcode
-/// In this example directive '#pragma omp flush' has pseudo clause 'flush'
+/// In this example directive '#pragma omp flush' has implicit clause 'flush'
/// with the variables 'a' and 'b'.
///
class OMPFlushClause : public OMPVarListClause<OMPFlushClause> {
@@ -1453,3 +1697,4 @@ public:
} // end namespace clang
#endif
+
diff --git a/include/clang/AST/OperationKinds.h b/include/clang/AST/OperationKinds.h
index aba88d6c5419..e3f012667727 100644
--- a/include/clang/AST/OperationKinds.h
+++ b/include/clang/AST/OperationKinds.h
@@ -12,8 +12,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_AST_OPERATION_KINDS_H
-#define LLVM_CLANG_AST_OPERATION_KINDS_H
+#ifndef LLVM_CLANG_AST_OPERATIONKINDS_H
+#define LLVM_CLANG_AST_OPERATIONKINDS_H
namespace clang {
diff --git a/include/clang/AST/ParentMap.h b/include/clang/AST/ParentMap.h
index eece8510e9c4..8945c413d268 100644
--- a/include/clang/AST/ParentMap.h
+++ b/include/clang/AST/ParentMap.h
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_PARENTMAP_H
-#define LLVM_CLANG_PARENTMAP_H
+#ifndef LLVM_CLANG_AST_PARENTMAP_H
+#define LLVM_CLANG_AST_PARENTMAP_H
namespace clang {
class Stmt;
diff --git a/include/clang/AST/PrettyPrinter.h b/include/clang/AST/PrettyPrinter.h
index 349f4c44a4e0..35ceabbd6b71 100644
--- a/include/clang/AST/PrettyPrinter.h
+++ b/include/clang/AST/PrettyPrinter.h
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_AST_PRETTY_PRINTER_H
-#define LLVM_CLANG_AST_PRETTY_PRINTER_H
+#ifndef LLVM_CLANG_AST_PRETTYPRINTER_H
+#define LLVM_CLANG_AST_PRETTYPRINTER_H
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
diff --git a/include/clang/AST/RawCommentList.h b/include/clang/AST/RawCommentList.h
index 8ba85c43f657..2e005ddbd027 100644
--- a/include/clang/AST/RawCommentList.h
+++ b/include/clang/AST/RawCommentList.h
@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_AST_RAW_COMMENT_LIST_H
-#define LLVM_CLANG_AST_RAW_COMMENT_LIST_H
+#ifndef LLVM_CLANG_AST_RAWCOMMENTLIST_H
+#define LLVM_CLANG_AST_RAWCOMMENTLIST_H
#include "clang/Basic/CommentOptions.h"
#include "clang/Basic/SourceManager.h"
diff --git a/include/clang/AST/RecordLayout.h b/include/clang/AST/RecordLayout.h
index 4befb4506212..7b7799884a3d 100644
--- a/include/clang/AST/RecordLayout.h
+++ b/include/clang/AST/RecordLayout.h
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_AST_LAYOUTINFO_H
-#define LLVM_CLANG_AST_LAYOUTINFO_H
+#ifndef LLVM_CLANG_AST_RECORDLAYOUT_H
+#define LLVM_CLANG_AST_RECORDLAYOUT_H
#include "clang/AST/CharUnits.h"
#include "clang/AST/DeclCXX.h"
diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h
index ff46ffb94e70..a1d36180d737 100644
--- a/include/clang/AST/RecursiveASTVisitor.h
+++ b/include/clang/AST/RecursiveASTVisitor.h
@@ -429,6 +429,7 @@ private:
bool TraverseFunctionHelper(FunctionDecl *D);
bool TraverseVarHelper(VarDecl *D);
bool TraverseOMPExecutableDirective(OMPExecutableDirective *S);
+ bool TraverseOMPLoopDirective(OMPLoopDirective *S);
bool TraverseOMPClause(OMPClause *C);
#define OPENMP_CLAUSE(Name, Class) bool Visit##Class(Class *C);
#include "clang/Basic/OpenMPKinds.def"
@@ -689,6 +690,7 @@ bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifier(
case NestedNameSpecifier::Namespace:
case NestedNameSpecifier::NamespaceAlias:
case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::Super:
return true;
case NestedNameSpecifier::TypeSpec:
@@ -713,6 +715,7 @@ bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifierLoc(
case NestedNameSpecifier::Namespace:
case NestedNameSpecifier::NamespaceAlias:
case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::Super:
return true;
case NestedNameSpecifier::TypeSpec:
@@ -940,6 +943,9 @@ DEF_TRAVERSE_TYPE(FunctionProtoType, {
for (const auto &E : T->exceptions()) {
TRY_TO(TraverseType(E));
}
+
+ if (Expr *NE = T->getNoexceptExpr())
+ TRY_TO(TraverseStmt(NE));
})
DEF_TRAVERSE_TYPE(UnresolvedUsingType, {})
@@ -1148,6 +1154,9 @@ DEF_TRAVERSE_TYPELOC(FunctionProtoType, {
for (const auto &E : T->exceptions()) {
TRY_TO(TraverseType(E));
}
+
+ if (Expr *NE = T->getNoexceptExpr())
+ TRY_TO(TraverseStmt(NE));
})
DEF_TRAVERSE_TYPELOC(UnresolvedUsingType, {})
@@ -2144,21 +2153,29 @@ bool RecursiveASTVisitor<Derived>::TraverseLambdaExpr(LambdaExpr *S) {
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()));
+ TypeLoc TL = S->getCallOperator()->getTypeSourceInfo()->getTypeLoc();
+ FunctionProtoTypeLoc Proto = TL.castAs<FunctionProtoTypeLoc>();
+
+ if (S->hasExplicitParameters() && S->hasExplicitResultType()) {
+ // Visit the whole type.
+ TRY_TO(TraverseTypeLoc(TL));
+ } else {
+ if (S->hasExplicitParameters()) {
+ // Visit parameters.
+ for (unsigned I = 0, N = Proto.getNumParams(); I != N; ++I) {
+ TRY_TO(TraverseDecl(Proto.getParam(I)));
}
+ } else if (S->hasExplicitResultType()) {
+ TRY_TO(TraverseTypeLoc(Proto.getReturnLoc()));
+ }
+
+ auto *T = Proto.getTypePtr();
+ for (const auto &E : T->exceptions()) {
+ TRY_TO(TraverseType(E));
}
+
+ if (Expr *NE = T->getNoexceptExpr())
+ TRY_TO(TraverseStmt(NE));
}
TRY_TO(TraverseLambdaBody(S));
@@ -2259,6 +2276,7 @@ DEF_TRAVERSE_STMT(CapturedStmt, { TRY_TO(TraverseDecl(S->getCapturedDecl())); })
DEF_TRAVERSE_STMT(CXXOperatorCallExpr, {})
DEF_TRAVERSE_STMT(OpaqueValueExpr, {})
+DEF_TRAVERSE_STMT(TypoExpr, {})
DEF_TRAVERSE_STMT(CUDAKernelCallExpr, {})
// These operators (all of them) do not need any action except
@@ -2275,6 +2293,7 @@ DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmPackExpr, {})
DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmExpr, {})
DEF_TRAVERSE_STMT(FunctionParmPackExpr, {})
DEF_TRAVERSE_STMT(MaterializeTemporaryExpr, {})
+DEF_TRAVERSE_STMT(CXXFoldExpr, {})
DEF_TRAVERSE_STMT(AtomicExpr, {})
// These literals (all of them) do not need any action.
@@ -2301,6 +2320,12 @@ bool RecursiveASTVisitor<Derived>::TraverseOMPExecutableDirective(
return true;
}
+template <typename Derived>
+bool
+RecursiveASTVisitor<Derived>::TraverseOMPLoopDirective(OMPLoopDirective *S) {
+ return TraverseOMPExecutableDirective(S);
+}
+
DEF_TRAVERSE_STMT(OMPParallelDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
@@ -2310,6 +2335,9 @@ DEF_TRAVERSE_STMT(OMPSimdDirective,
DEF_TRAVERSE_STMT(OMPForDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
+DEF_TRAVERSE_STMT(OMPForSimdDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
DEF_TRAVERSE_STMT(OMPSectionsDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
@@ -2330,6 +2358,9 @@ DEF_TRAVERSE_STMT(OMPCriticalDirective, {
DEF_TRAVERSE_STMT(OMPParallelForDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
+DEF_TRAVERSE_STMT(OMPParallelForSimdDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
DEF_TRAVERSE_STMT(OMPParallelSectionsDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
@@ -2348,6 +2379,18 @@ DEF_TRAVERSE_STMT(OMPTaskwaitDirective,
DEF_TRAVERSE_STMT(OMPFlushDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
+DEF_TRAVERSE_STMT(OMPOrderedDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPAtomicDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPTargetDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPTeamsDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
// OpenMP clauses.
template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) {
@@ -2437,6 +2480,31 @@ RecursiveASTVisitor<Derived>::VisitOMPMergeableClause(OMPMergeableClause *) {
}
template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPReadClause(OMPReadClause *) {
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPWriteClause(OMPWriteClause *) {
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPUpdateClause(OMPUpdateClause *) {
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPCaptureClause(OMPCaptureClause *) {
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPSeqCstClause(OMPSeqCstClause *) {
+ return true;
+}
+
+template <typename Derived>
template <typename T>
bool RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) {
for (auto *E : Node->varlists()) {
@@ -2448,6 +2516,9 @@ bool RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) {
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPPrivateClause(OMPPrivateClause *C) {
TRY_TO(VisitOMPClauseList(C));
+ for (auto *E : C->private_copies()) {
+ TRY_TO(TraverseStmt(E));
+ }
return true;
}
@@ -2455,6 +2526,12 @@ template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPFirstprivateClause(
OMPFirstprivateClause *C) {
TRY_TO(VisitOMPClauseList(C));
+ for (auto *E : C->private_copies()) {
+ TRY_TO(TraverseStmt(E));
+ }
+ for (auto *E : C->inits()) {
+ TRY_TO(TraverseStmt(E));
+ }
return true;
}
diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h
index fb94097cfac7..eb6836f88699 100644
--- a/include/clang/AST/Stmt.h
+++ b/include/clang/AST/Stmt.h
@@ -212,7 +212,7 @@ protected:
unsigned HasTemplateKWAndArgsInfo : 1;
unsigned HasFoundDecl : 1;
unsigned HadMultipleCandidates : 1;
- unsigned RefersToEnclosingLocal : 1;
+ unsigned RefersToEnclosingVariableOrCapture : 1;
};
class CastExprBitfields {
@@ -393,6 +393,10 @@ public:
/// statement, such as ExprWithCleanups or ImplicitCastExpr nodes.
Stmt *IgnoreImplicit();
+ /// \brief Skip no-op (attributed, compound) container stmts and skip captured
+ /// stmt at the top, if \a IgnoreCaptured is true.
+ Stmt *IgnoreContainers(bool IgnoreCaptured = false);
+
const Stmt *stripLabelLikeStatements() const;
Stmt *stripLabelLikeStatements() {
return const_cast<Stmt*>(
@@ -548,14 +552,17 @@ public:
///
class CompoundStmt : public Stmt {
Stmt** Body;
- SourceLocation LBracLoc, RBracLoc;
+ SourceLocation LBraceLoc, RBraceLoc;
+
+ friend class ASTStmtReader;
+
public:
CompoundStmt(const ASTContext &C, ArrayRef<Stmt*> Stmts,
SourceLocation LB, SourceLocation RB);
// \brief Build an empty compound statement with a location.
explicit CompoundStmt(SourceLocation Loc)
- : Stmt(CompoundStmtClass), Body(nullptr), LBracLoc(Loc), RBracLoc(Loc) {
+ : Stmt(CompoundStmtClass), Body(nullptr), LBraceLoc(Loc), RBraceLoc(Loc) {
CompoundStmtBits.NumStmts = 0;
}
@@ -614,13 +621,11 @@ public:
return const_reverse_body_iterator(body_begin());
}
- SourceLocation getLocStart() const LLVM_READONLY { return LBracLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return RBracLoc; }
+ SourceLocation getLocStart() const LLVM_READONLY { return LBraceLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return RBraceLoc; }
- SourceLocation getLBracLoc() const { return LBracLoc; }
- void setLBracLoc(SourceLocation L) { LBracLoc = L; }
- SourceLocation getRBracLoc() const { return RBracLoc; }
- void setRBracLoc(SourceLocation L) { RBracLoc = L; }
+ SourceLocation getLBracLoc() const { return LBraceLoc; }
+ SourceLocation getRBracLoc() const { return RBraceLoc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == CompoundStmtClass;
@@ -846,7 +851,7 @@ public:
SourceLocation getAttrLoc() const { return AttrLoc; }
ArrayRef<const Attr*> getAttrs() const {
- return ArrayRef<const Attr*>(getAttrArrayPtr(), NumAttrs);
+ return llvm::makeArrayRef(getAttrArrayPtr(), NumAttrs);
}
Stmt *getSubStmt() { return SubStmt; }
const Stmt *getSubStmt() const { return SubStmt; }
@@ -1010,7 +1015,7 @@ public:
SourceLocation getLocStart() const LLVM_READONLY { return SwitchLoc; }
SourceLocation getLocEnd() const LLVM_READONLY {
- return SubExprs[BODY]->getLocEnd();
+ return SubExprs[BODY] ? SubExprs[BODY]->getLocEnd() : SubExprs[COND]->getLocEnd();
}
// Iterators
@@ -1580,18 +1585,21 @@ public:
Kind MyKind;
std::string Str;
unsigned OperandNo;
+
+ // Source range for operand references.
+ CharSourceRange Range;
public:
AsmStringPiece(const std::string &S) : MyKind(String), Str(S) {}
- AsmStringPiece(unsigned OpNo, char Modifier)
- : MyKind(Operand), Str(), OperandNo(OpNo) {
- Str += Modifier;
+ AsmStringPiece(unsigned OpNo, const std::string &S, SourceLocation Begin,
+ SourceLocation End)
+ : MyKind(Operand), Str(S), OperandNo(OpNo),
+ Range(CharSourceRange::getCharRange(Begin, End)) {
}
bool isString() const { return MyKind == String; }
bool isOperand() const { return MyKind == Operand; }
const std::string &getString() const {
- assert(isString());
return Str;
}
@@ -1600,12 +1608,14 @@ public:
return OperandNo;
}
+ CharSourceRange getRange() const {
+ assert(isOperand() && "Range is currently used only for Operands.");
+ return Range;
+ }
+
/// getModifier - Get the modifier for this operand, if present. This
/// returns '\0' if there was no modifier.
- char getModifier() const {
- assert(isOperand());
- return Str[0];
- }
+ char getModifier() const;
};
/// AnalyzeAsmString - Analyze the asm string of the current asm, decomposing
@@ -1780,14 +1790,14 @@ public:
//===--- Other ---===//
ArrayRef<StringRef> getAllConstraints() const {
- return ArrayRef<StringRef>(Constraints, NumInputs + NumOutputs);
+ return llvm::makeArrayRef(Constraints, NumInputs + NumOutputs);
}
ArrayRef<StringRef> getClobbers() const {
- return ArrayRef<StringRef>(Clobbers, NumClobbers);
+ return llvm::makeArrayRef(Clobbers, NumClobbers);
}
ArrayRef<Expr*> getAllExprs() const {
- return ArrayRef<Expr*>(reinterpret_cast<Expr**>(Exprs),
- NumInputs + NumOutputs);
+ return llvm::makeArrayRef(reinterpret_cast<Expr**>(Exprs),
+ NumInputs + NumOutputs);
}
StringRef getClobber(unsigned i) const { return getClobbers()[i]; }
@@ -1892,24 +1902,22 @@ 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,
- int HandlerIndex, int HandlerParentIndex);
+ SourceLocation TryLoc,
+ Stmt *TryBlock,
+ Stmt *Handler);
friend class ASTReader;
friend class ASTStmtReader;
explicit SEHTryStmt(EmptyShell E) : Stmt(SEHTryStmtClass, E) { }
public:
- static SEHTryStmt *Create(const ASTContext &C, bool isCXXTry,
+ static SEHTryStmt* Create(const ASTContext &C, bool isCXXTry,
SourceLocation TryLoc, Stmt *TryBlock,
- Stmt *Handler, int HandlerIndex,
- int HandlerParentIndex);
+ Stmt *Handler);
SourceLocation getLocStart() const LLVM_READONLY { return getTryLoc(); }
SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); }
@@ -1936,9 +1944,6 @@ 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.
@@ -1977,15 +1982,18 @@ public:
/// @endcode
class CapturedStmt : public Stmt {
public:
- /// \brief The different capture forms: by 'this' or by reference, etc.
+ /// \brief The different capture forms: by 'this', by reference, capture for
+ /// variable-length array type etc.
enum VariableCaptureKind {
VCK_This,
- VCK_ByRef
+ VCK_ByRef,
+ VCK_VLAType,
};
- /// \brief Describes the capture of either a variable or 'this'.
+ /// \brief Describes the capture of either a variable, or 'this', or
+ /// variable-length array type.
class Capture {
- llvm::PointerIntPair<VarDecl *, 1, VariableCaptureKind> VarAndKind;
+ llvm::PointerIntPair<VarDecl *, 2, VariableCaptureKind> VarAndKind;
SourceLocation Loc;
public:
@@ -2007,6 +2015,10 @@ public:
case VCK_ByRef:
assert(Var && "capturing by reference must have a variable!");
break;
+ case VCK_VLAType:
+ assert(!Var &&
+ "Variable-length array type capture cannot have a variable!");
+ break;
}
}
@@ -2021,13 +2033,20 @@ public:
bool capturesThis() const { return getCaptureKind() == VCK_This; }
/// \brief Determine whether this capture handles a variable.
- bool capturesVariable() const { return getCaptureKind() != VCK_This; }
+ bool capturesVariable() const { return getCaptureKind() == VCK_ByRef; }
+
+ /// \brief Determine whether this capture handles a variable-length array
+ /// type.
+ bool capturesVariableArrayType() const {
+ return getCaptureKind() == VCK_VLAType;
+ }
/// \brief Retrieve the declaration of the variable being captured.
///
- /// This operation is only valid if this capture does not capture 'this'.
+ /// This operation is only valid if this capture captures a variable.
VarDecl *getCapturedVar() const {
- assert(!capturesThis() && "No variable available for 'this' capture");
+ assert(capturesVariable() &&
+ "No variable available for 'this' or VAT capture");
return VarAndKind.getPointer();
}
friend class ASTStmtReader;
diff --git a/include/clang/AST/StmtGraphTraits.h b/include/clang/AST/StmtGraphTraits.h
index a3e9e1e093f6..ab636a5ddc48 100644
--- a/include/clang/AST/StmtGraphTraits.h
+++ b/include/clang/AST/StmtGraphTraits.h
@@ -12,8 +12,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_AST_STMT_GRAPHTRAITS_H
-#define LLVM_CLANG_AST_STMT_GRAPHTRAITS_H
+#ifndef LLVM_CLANG_AST_STMTGRAPHTRAITS_H
+#define LLVM_CLANG_AST_STMTGRAPHTRAITS_H
#include "clang/AST/Stmt.h"
#include "llvm/ADT/DepthFirstIterator.h"
diff --git a/include/clang/AST/StmtIterator.h b/include/clang/AST/StmtIterator.h
index 18c55166beba..6ffe74f2d7fb 100644
--- a/include/clang/AST/StmtIterator.h
+++ b/include/clang/AST/StmtIterator.h
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_AST_STMT_ITR_H
-#define LLVM_CLANG_AST_STMT_ITR_H
+#ifndef LLVM_CLANG_AST_STMTITERATOR_H
+#define LLVM_CLANG_AST_STMTITERATOR_H
#include "llvm/Support/Compiler.h"
#include "llvm/Support/DataTypes.h"
diff --git a/include/clang/AST/StmtOpenMP.h b/include/clang/AST/StmtOpenMP.h
index db02afe0568b..aed7691cf73a 100644
--- a/include/clang/AST/StmtOpenMP.h
+++ b/include/clang/AST/StmtOpenMP.h
@@ -128,6 +128,13 @@ public:
operator bool() { return Current != End; }
};
+ /// \brief Gets a single clause of the specified kind \a K associated with the
+ /// current directive iff there is only one clause of this kind (and assertion
+ /// is fired if there is more than one clause is associated with the
+ /// directive). Returns nullptr if no clause of kind \a K is associated with
+ /// the directive.
+ const OMPClause *getSingleClause(OpenMPClauseKind K) const;
+
/// \brief Returns starting location of directive kind.
SourceLocation getLocStart() const { return StartLoc; }
/// \brief Returns ending location of directive.
@@ -238,6 +245,353 @@ public:
}
};
+/// \brief This is a common base class for loop directives ('omp simd', 'omp
+/// for', 'omp for simd' etc.). It is responsible for the loop code generation.
+///
+class OMPLoopDirective : public OMPExecutableDirective {
+ friend class ASTStmtReader;
+ /// \brief Number of collapsed loops as specified by 'collapse' clause.
+ unsigned CollapsedNum;
+
+ /// \brief Offsets to the stored exprs.
+ /// This enumeration contains offsets to all the pointers to children
+ /// expressions stored in OMPLoopDirective.
+ /// The first 9 children are nesessary for all the loop directives, and
+ /// the next 7 are specific to the worksharing ones.
+ /// After the fixed children, three arrays of length CollapsedNum are
+ /// allocated: loop counters, their updates and final values.
+ ///
+ enum {
+ AssociatedStmtOffset = 0,
+ IterationVariableOffset = 1,
+ LastIterationOffset = 2,
+ CalcLastIterationOffset = 3,
+ PreConditionOffset = 4,
+ CondOffset = 5,
+ SeparatedCondOffset = 6,
+ InitOffset = 7,
+ IncOffset = 8,
+ // The '...End' enumerators do not correspond to child expressions - they
+ // specify the offset to the end (and start of the following counters/
+ // updates/finals arrays).
+ DefaultEnd = 9,
+ // The following 7 exprs are used by worksharing loops only.
+ IsLastIterVariableOffset = 9,
+ LowerBoundVariableOffset = 10,
+ UpperBoundVariableOffset = 11,
+ StrideVariableOffset = 12,
+ EnsureUpperBoundOffset = 13,
+ NextLowerBoundOffset = 14,
+ NextUpperBoundOffset = 15,
+ // Offset to the end (and start of the following counters/updates/finals
+ // arrays) for worksharing loop directives.
+ WorksharingEnd = 16,
+ };
+
+ /// \brief Get the counters storage.
+ MutableArrayRef<Expr *> getCounters() {
+ Expr **Storage = reinterpret_cast<Expr **>(
+ &(*(std::next(child_begin(), getArraysOffset(getDirectiveKind())))));
+ return MutableArrayRef<Expr *>(Storage, CollapsedNum);
+ }
+
+ /// \brief Get the updates storage.
+ MutableArrayRef<Expr *> getUpdates() {
+ Expr **Storage = reinterpret_cast<Expr **>(
+ &*std::next(child_begin(),
+ getArraysOffset(getDirectiveKind()) + CollapsedNum));
+ return MutableArrayRef<Expr *>(Storage, CollapsedNum);
+ }
+
+ /// \brief Get the final counter updates storage.
+ MutableArrayRef<Expr *> getFinals() {
+ Expr **Storage = reinterpret_cast<Expr **>(
+ &*std::next(child_begin(),
+ getArraysOffset(getDirectiveKind()) + 2 * CollapsedNum));
+ return MutableArrayRef<Expr *>(Storage, CollapsedNum);
+ }
+
+protected:
+ /// \brief Build instance of loop directive of class \a Kind.
+ ///
+ /// \param SC Statement class.
+ /// \param Kind Kind of OpenMP directive.
+ /// \param StartLoc Starting location of the directive (directive keyword).
+ /// \param EndLoc Ending location of the directive.
+ /// \param CollapsedNum Number of collapsed loops from 'collapse' clause.
+ /// \param NumClauses Number of clauses.
+ /// \param NumSpecialChildren Number of additional directive-specific stmts.
+ ///
+ template <typename T>
+ OMPLoopDirective(const T *That, StmtClass SC, OpenMPDirectiveKind Kind,
+ SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, unsigned NumClauses,
+ unsigned NumSpecialChildren = 0)
+ : OMPExecutableDirective(That, SC, Kind, StartLoc, EndLoc, NumClauses,
+ numLoopChildren(CollapsedNum, Kind) +
+ NumSpecialChildren),
+ CollapsedNum(CollapsedNum) {}
+
+ /// \brief Offset to the start of children expression arrays.
+ static unsigned getArraysOffset(OpenMPDirectiveKind Kind) {
+ return isOpenMPWorksharingDirective(Kind) ? WorksharingEnd
+ : DefaultEnd;
+ }
+
+ /// \brief Children number.
+ static unsigned numLoopChildren(unsigned CollapsedNum,
+ OpenMPDirectiveKind Kind) {
+ return getArraysOffset(Kind) +
+ 3 * CollapsedNum; // Counters, Updates and Finals
+ }
+
+ void setIterationVariable(Expr *IV) {
+ *std::next(child_begin(), IterationVariableOffset) = IV;
+ }
+ void setLastIteration(Expr *LI) {
+ *std::next(child_begin(), LastIterationOffset) = LI;
+ }
+ void setCalcLastIteration(Expr *CLI) {
+ *std::next(child_begin(), CalcLastIterationOffset) = CLI;
+ }
+ void setPreCond(Expr *PC) {
+ *std::next(child_begin(), PreConditionOffset) = PC;
+ }
+ void setCond(Expr *Cond, Expr *SeparatedCond) {
+ *std::next(child_begin(), CondOffset) = Cond;
+ *std::next(child_begin(), SeparatedCondOffset) = SeparatedCond;
+ }
+ void setInit(Expr *Init) { *std::next(child_begin(), InitOffset) = Init; }
+ void setInc(Expr *Inc) { *std::next(child_begin(), IncOffset) = Inc; }
+ void setIsLastIterVariable(Expr *IL) {
+ assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+ "expected worksharing loop directive");
+ *std::next(child_begin(), IsLastIterVariableOffset) = IL;
+ }
+ void setLowerBoundVariable(Expr *LB) {
+ assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+ "expected worksharing loop directive");
+ *std::next(child_begin(), LowerBoundVariableOffset) = LB;
+ }
+ void setUpperBoundVariable(Expr *UB) {
+ assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+ "expected worksharing loop directive");
+ *std::next(child_begin(), UpperBoundVariableOffset) = UB;
+ }
+ void setStrideVariable(Expr *ST) {
+ assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+ "expected worksharing loop directive");
+ *std::next(child_begin(), StrideVariableOffset) = ST;
+ }
+ void setEnsureUpperBound(Expr *EUB) {
+ assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+ "expected worksharing loop directive");
+ *std::next(child_begin(), EnsureUpperBoundOffset) = EUB;
+ }
+ void setNextLowerBound(Expr *NLB) {
+ assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+ "expected worksharing loop directive");
+ *std::next(child_begin(), NextLowerBoundOffset) = NLB;
+ }
+ void setNextUpperBound(Expr *NUB) {
+ assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+ "expected worksharing loop directive");
+ *std::next(child_begin(), NextUpperBoundOffset) = NUB;
+ }
+ void setCounters(ArrayRef<Expr *> A);
+ void setUpdates(ArrayRef<Expr *> A);
+ void setFinals(ArrayRef<Expr *> A);
+
+public:
+ /// \brief The expressions built for the OpenMP loop CodeGen for the
+ /// whole collapsed loop nest.
+ struct HelperExprs {
+ /// \brief Loop iteration variable.
+ Expr *IterationVarRef;
+ /// \brief Loop last iteration number.
+ Expr *LastIteration;
+ /// \brief Calculation of last iteration.
+ Expr *CalcLastIteration;
+ /// \brief Loop pre-condition.
+ Expr *PreCond;
+ /// \brief Loop condition.
+ Expr *Cond;
+ /// \brief A condition with 1 iteration separated.
+ Expr *SeparatedCond;
+ /// \brief Loop iteration variable init.
+ Expr *Init;
+ /// \brief Loop increment.
+ Expr *Inc;
+ /// \brief IsLastIteration - local flag variable passed to runtime.
+ Expr *IL;
+ /// \brief LowerBound - local variable passed to runtime.
+ Expr *LB;
+ /// \brief UpperBound - local variable passed to runtime.
+ Expr *UB;
+ /// \brief Stride - local variable passed to runtime.
+ Expr *ST;
+ /// \brief EnsureUpperBound -- expression LB = min(LB, NumIterations).
+ Expr *EUB;
+ /// \brief Update of LowerBound for statically sheduled 'omp for' loops.
+ Expr *NLB;
+ /// \brief Update of UpperBound for statically sheduled 'omp for' loops.
+ Expr *NUB;
+ /// \brief Counters Loop counters.
+ SmallVector<Expr *, 4> Counters;
+ /// \brief Expressions for loop counters update for CodeGen.
+ SmallVector<Expr *, 4> Updates;
+ /// \brief Final loop counter values for GodeGen.
+ SmallVector<Expr *, 4> Finals;
+
+ /// \brief Check if all the expressions are built (does not check the
+ /// worksharing ones).
+ bool builtAll() {
+ return IterationVarRef != nullptr && LastIteration != nullptr &&
+ PreCond != nullptr && Cond != nullptr &&
+ SeparatedCond != nullptr && Init != nullptr && Inc != nullptr;
+ }
+
+ /// \brief Initialize all the fields to null.
+ /// \param Size Number of elements in the counters/finals/updates arrays.
+ void clear(unsigned Size) {
+ IterationVarRef = nullptr;
+ LastIteration = nullptr;
+ CalcLastIteration = nullptr;
+ PreCond = nullptr;
+ Cond = nullptr;
+ SeparatedCond = nullptr;
+ Init = nullptr;
+ Inc = nullptr;
+ IL = nullptr;
+ LB = nullptr;
+ UB = nullptr;
+ ST = nullptr;
+ EUB = nullptr;
+ NLB = nullptr;
+ NUB = nullptr;
+ Counters.resize(Size);
+ Updates.resize(Size);
+ Finals.resize(Size);
+ for (unsigned i = 0; i < Size; ++i) {
+ Counters[i] = nullptr;
+ Updates[i] = nullptr;
+ Finals[i] = nullptr;
+ }
+ }
+ };
+
+ /// \brief Get number of collapsed loops.
+ unsigned getCollapsedNumber() const { return CollapsedNum; }
+
+ Expr *getIterationVariable() const {
+ return const_cast<Expr *>(reinterpret_cast<const Expr *>(
+ *std::next(child_begin(), IterationVariableOffset)));
+ }
+ Expr *getLastIteration() const {
+ return const_cast<Expr *>(reinterpret_cast<const Expr *>(
+ *std::next(child_begin(), LastIterationOffset)));
+ }
+ Expr *getCalcLastIteration() const {
+ return const_cast<Expr *>(reinterpret_cast<const Expr *>(
+ *std::next(child_begin(), CalcLastIterationOffset)));
+ }
+ Expr *getPreCond() const {
+ return const_cast<Expr *>(reinterpret_cast<const Expr *>(
+ *std::next(child_begin(), PreConditionOffset)));
+ }
+ Expr *getCond(bool SeparateIter) const {
+ return const_cast<Expr *>(reinterpret_cast<const Expr *>(
+ *std::next(child_begin(),
+ (SeparateIter ? SeparatedCondOffset : CondOffset))));
+ }
+ Expr *getInit() const {
+ return const_cast<Expr *>(
+ reinterpret_cast<const Expr *>(*std::next(child_begin(), InitOffset)));
+ }
+ Expr *getInc() const {
+ return const_cast<Expr *>(
+ reinterpret_cast<const Expr *>(*std::next(child_begin(), IncOffset)));
+ }
+ Expr *getIsLastIterVariable() const {
+ assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+ "expected worksharing loop directive");
+ return const_cast<Expr *>(reinterpret_cast<const Expr *>(
+ *std::next(child_begin(), IsLastIterVariableOffset)));
+ }
+ Expr *getLowerBoundVariable() const {
+ assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+ "expected worksharing loop directive");
+ return const_cast<Expr *>(reinterpret_cast<const Expr *>(
+ *std::next(child_begin(), LowerBoundVariableOffset)));
+ }
+ Expr *getUpperBoundVariable() const {
+ assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+ "expected worksharing loop directive");
+ return const_cast<Expr *>(reinterpret_cast<const Expr *>(
+ *std::next(child_begin(), UpperBoundVariableOffset)));
+ }
+ Expr *getStrideVariable() const {
+ assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+ "expected worksharing loop directive");
+ return const_cast<Expr *>(reinterpret_cast<const Expr *>(
+ *std::next(child_begin(), StrideVariableOffset)));
+ }
+ Expr *getEnsureUpperBound() const {
+ assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+ "expected worksharing loop directive");
+ return const_cast<Expr *>(reinterpret_cast<const Expr *>(
+ *std::next(child_begin(), EnsureUpperBoundOffset)));
+ }
+ Expr *getNextLowerBound() const {
+ assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+ "expected worksharing loop directive");
+ return const_cast<Expr *>(reinterpret_cast<const Expr *>(
+ *std::next(child_begin(), NextLowerBoundOffset)));
+ }
+ Expr *getNextUpperBound() const {
+ assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+ "expected worksharing loop directive");
+ return const_cast<Expr *>(reinterpret_cast<const Expr *>(
+ *std::next(child_begin(), NextUpperBoundOffset)));
+ }
+ const Stmt *getBody() const {
+ // This relies on the loop form is already checked by Sema.
+ Stmt *Body = getAssociatedStmt()->IgnoreContainers(true);
+ Body = cast<ForStmt>(Body)->getBody();
+ for (unsigned Cnt = 1; Cnt < CollapsedNum; ++Cnt) {
+ Body = Body->IgnoreContainers();
+ Body = cast<ForStmt>(Body)->getBody();
+ }
+ return Body;
+ }
+
+ ArrayRef<Expr *> counters() { return getCounters(); }
+
+ ArrayRef<Expr *> counters() const {
+ return const_cast<OMPLoopDirective *>(this)->getCounters();
+ }
+
+ ArrayRef<Expr *> updates() { return getUpdates(); }
+
+ ArrayRef<Expr *> updates() const {
+ return const_cast<OMPLoopDirective *>(this)->getUpdates();
+ }
+
+ ArrayRef<Expr *> finals() { return getFinals(); }
+
+ ArrayRef<Expr *> finals() const {
+ return const_cast<OMPLoopDirective *>(this)->getFinals();
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPSimdDirectiveClass ||
+ T->getStmtClass() == OMPForDirectiveClass ||
+ T->getStmtClass() == OMPForSimdDirectiveClass ||
+ T->getStmtClass() == OMPParallelForDirectiveClass ||
+ T->getStmtClass() == OMPParallelForSimdDirectiveClass;
+ }
+};
+
/// \brief This represents '#pragma omp simd' directive.
///
/// \code
@@ -247,10 +601,8 @@ public:
/// with the variables 'a' and 'b', 'linear' with variables 'i', 'j' and
/// linear step 's', 'reduction' with operator '+' and variables 'c' and 'd'.
///
-class OMPSimdDirective : public OMPExecutableDirective {
+class OMPSimdDirective : public OMPLoopDirective {
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.
@@ -260,9 +612,8 @@ class OMPSimdDirective : public OMPExecutableDirective {
///
OMPSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, unsigned NumClauses)
- : OMPExecutableDirective(this, OMPSimdDirectiveClass, OMPD_simd, StartLoc,
- EndLoc, NumClauses, 1),
- CollapsedNum(CollapsedNum) {}
+ : OMPLoopDirective(this, OMPSimdDirectiveClass, OMPD_simd, StartLoc,
+ EndLoc, CollapsedNum, NumClauses) {}
/// \brief Build an empty directive.
///
@@ -270,10 +621,9 @@ class OMPSimdDirective : public OMPExecutableDirective {
/// \param NumClauses Number of clauses.
///
explicit OMPSimdDirective(unsigned CollapsedNum, unsigned NumClauses)
- : OMPExecutableDirective(this, OMPSimdDirectiveClass, OMPD_simd,
- SourceLocation(), SourceLocation(), NumClauses,
- 1),
- CollapsedNum(CollapsedNum) {}
+ : OMPLoopDirective(this, OMPSimdDirectiveClass, OMPD_simd,
+ SourceLocation(), SourceLocation(), CollapsedNum,
+ NumClauses) {}
public:
/// \brief Creates directive with a list of \a Clauses.
@@ -284,11 +634,13 @@ public:
/// \param CollapsedNum Number of collapsed loops.
/// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
+ /// \param Exprs Helper expressions for CodeGen.
///
static OMPSimdDirective *Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation EndLoc, unsigned CollapsedNum,
ArrayRef<OMPClause *> Clauses,
- Stmt *AssociatedStmt);
+ Stmt *AssociatedStmt,
+ const HelperExprs &Exprs);
/// \brief Creates an empty directive with the place
/// for \a NumClauses clauses.
@@ -300,8 +652,6 @@ public:
static OMPSimdDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
unsigned CollapsedNum, EmptyShell);
- unsigned getCollapsedNumber() const { return CollapsedNum; }
-
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPSimdDirectiveClass;
}
@@ -316,10 +666,8 @@ public:
/// variables 'a' and 'b' and 'reduction' with operator '+' and variables 'c'
/// and 'd'.
///
-class OMPForDirective : public OMPExecutableDirective {
+class OMPForDirective : public OMPLoopDirective {
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.
@@ -329,9 +677,8 @@ class OMPForDirective : public OMPExecutableDirective {
///
OMPForDirective(SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, unsigned NumClauses)
- : OMPExecutableDirective(this, OMPForDirectiveClass, OMPD_for, StartLoc,
- EndLoc, NumClauses, 1),
- CollapsedNum(CollapsedNum) {}
+ : OMPLoopDirective(this, OMPForDirectiveClass, OMPD_for, StartLoc, EndLoc,
+ CollapsedNum, NumClauses) {}
/// \brief Build an empty directive.
///
@@ -339,10 +686,8 @@ class OMPForDirective : public OMPExecutableDirective {
/// \param NumClauses Number of clauses.
///
explicit OMPForDirective(unsigned CollapsedNum, unsigned NumClauses)
- : OMPExecutableDirective(this, OMPForDirectiveClass, OMPD_for,
- SourceLocation(), SourceLocation(), NumClauses,
- 1),
- CollapsedNum(CollapsedNum) {}
+ : OMPLoopDirective(this, OMPForDirectiveClass, OMPD_for, SourceLocation(),
+ SourceLocation(), CollapsedNum, NumClauses) {}
public:
/// \brief Creates directive with a list of \a Clauses.
@@ -353,11 +698,13 @@ public:
/// \param CollapsedNum Number of collapsed loops.
/// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
+ /// \param Exprs Helper expressions for CodeGen.
///
static OMPForDirective *Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation EndLoc, unsigned CollapsedNum,
ArrayRef<OMPClause *> Clauses,
- Stmt *AssociatedStmt);
+ Stmt *AssociatedStmt,
+ const HelperExprs &Exprs);
/// \brief Creates an empty directive with the place
/// for \a NumClauses clauses.
@@ -369,13 +716,76 @@ public:
static OMPForDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
unsigned CollapsedNum, EmptyShell);
- unsigned getCollapsedNumber() const { return CollapsedNum; }
-
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPForDirectiveClass;
}
};
+/// \brief This represents '#pragma omp for simd' directive.
+///
+/// \code
+/// #pragma omp for simd private(a,b) linear(i,j:s) reduction(+:c,d)
+/// \endcode
+/// In this example directive '#pragma omp for simd' has clauses 'private'
+/// with the variables 'a' and 'b', 'linear' with variables 'i', 'j' and
+/// linear step 's', 'reduction' with operator '+' and variables 'c' and 'd'.
+///
+class OMPForSimdDirective : public OMPLoopDirective {
+ friend class ASTStmtReader;
+ /// \brief Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ OMPForSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, unsigned NumClauses)
+ : OMPLoopDirective(this, OMPForSimdDirectiveClass, OMPD_for_simd,
+ StartLoc, EndLoc, CollapsedNum, NumClauses) {}
+
+ /// \brief Build an empty directive.
+ ///
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPForSimdDirective(unsigned CollapsedNum, unsigned NumClauses)
+ : OMPLoopDirective(this, OMPForSimdDirectiveClass, OMPD_for_simd,
+ SourceLocation(), SourceLocation(), CollapsedNum,
+ NumClauses) {}
+
+public:
+ /// \brief Creates directive with a list of \a Clauses.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param CollapsedNum Number of collapsed loops.
+ /// \param Clauses List of clauses.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ /// \param Exprs Helper expressions for CodeGen.
+ ///
+ static OMPForSimdDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt, const HelperExprs &Exprs);
+
+ /// \brief Creates an empty directive with the place
+ /// for \a NumClauses clauses.
+ ///
+ /// \param C AST context.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPForSimdDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ unsigned CollapsedNum, EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPForSimdDirectiveClass;
+ }
+};
+
/// \brief This represents '#pragma omp sections' directive.
///
/// \code
@@ -657,10 +1067,8 @@ public:
/// with the variables 'a' and 'b' and 'reduction' with operator '+' and
/// variables 'c' and 'd'.
///
-class OMPParallelForDirective : public OMPExecutableDirective {
+class OMPParallelForDirective : public OMPLoopDirective {
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.
@@ -670,10 +1078,8 @@ class OMPParallelForDirective : public OMPExecutableDirective {
///
OMPParallelForDirective(SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, unsigned NumClauses)
- : OMPExecutableDirective(this, OMPParallelForDirectiveClass,
- OMPD_parallel_for, StartLoc, EndLoc, NumClauses,
- 1),
- CollapsedNum(CollapsedNum) {}
+ : OMPLoopDirective(this, OMPParallelForDirectiveClass, OMPD_parallel_for,
+ StartLoc, EndLoc, CollapsedNum, NumClauses) {}
/// \brief Build an empty directive.
///
@@ -681,10 +1087,9 @@ class OMPParallelForDirective : public OMPExecutableDirective {
/// \param NumClauses Number of clauses.
///
explicit OMPParallelForDirective(unsigned CollapsedNum, unsigned NumClauses)
- : OMPExecutableDirective(this, OMPParallelForDirectiveClass,
- OMPD_parallel_for, SourceLocation(),
- SourceLocation(), NumClauses, 1),
- CollapsedNum(CollapsedNum) {}
+ : OMPLoopDirective(this, OMPParallelForDirectiveClass, OMPD_parallel_for,
+ SourceLocation(), SourceLocation(), CollapsedNum,
+ NumClauses) {}
public:
/// \brief Creates directive with a list of \a Clauses.
@@ -695,11 +1100,12 @@ public:
/// \param CollapsedNum Number of collapsed loops.
/// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
+ /// \param Exprs Helper expressions for CodeGen.
///
static OMPParallelForDirective *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
- Stmt *AssociatedStmt);
+ Stmt *AssociatedStmt, const HelperExprs &Exprs);
/// \brief Creates an empty directive with the place
/// for \a NumClauses clauses.
@@ -713,13 +1119,80 @@ public:
unsigned CollapsedNum,
EmptyShell);
- unsigned getCollapsedNumber() const { return CollapsedNum; }
-
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPParallelForDirectiveClass;
}
};
+/// \brief This represents '#pragma omp parallel for simd' directive.
+///
+/// \code
+/// #pragma omp parallel for simd private(a,b) linear(i,j:s) reduction(+:c,d)
+/// \endcode
+/// In this example directive '#pragma omp parallel for simd' has clauses
+/// 'private' with the variables 'a' and 'b', 'linear' with variables 'i', 'j'
+/// and linear step 's', 'reduction' with operator '+' and variables 'c' and
+/// 'd'.
+///
+class OMPParallelForSimdDirective : public OMPLoopDirective {
+ friend class ASTStmtReader;
+ /// \brief Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ OMPParallelForSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, unsigned NumClauses)
+ : OMPLoopDirective(this, OMPParallelForSimdDirectiveClass,
+ OMPD_parallel_for_simd, StartLoc, EndLoc, CollapsedNum,
+ NumClauses) {}
+
+ /// \brief Build an empty directive.
+ ///
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPParallelForSimdDirective(unsigned CollapsedNum,
+ unsigned NumClauses)
+ : OMPLoopDirective(this, OMPParallelForSimdDirectiveClass,
+ OMPD_parallel_for_simd, SourceLocation(),
+ SourceLocation(), CollapsedNum, NumClauses) {}
+
+public:
+ /// \brief Creates directive with a list of \a Clauses.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param CollapsedNum Number of collapsed loops.
+ /// \param Clauses List of clauses.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ /// \param Exprs Helper expressions for CodeGen.
+ ///
+ static OMPParallelForSimdDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt, const HelperExprs &Exprs);
+
+ /// \brief Creates an empty directive with the place
+ /// for \a NumClauses clauses.
+ ///
+ /// \param C AST context.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPParallelForSimdDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ unsigned CollapsedNum,
+ EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPParallelForSimdDirectiveClass;
+ }
+};
+
/// \brief This represents '#pragma omp parallel sections' directive.
///
/// \code
@@ -1028,6 +1501,253 @@ public:
}
};
+/// \brief This represents '#pragma omp ordered' directive.
+///
+/// \code
+/// #pragma omp ordered
+/// \endcode
+///
+class OMPOrderedDirective : public OMPExecutableDirective {
+ friend class ASTStmtReader;
+ /// \brief Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ ///
+ OMPOrderedDirective(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPExecutableDirective(this, OMPOrderedDirectiveClass, OMPD_ordered,
+ StartLoc, EndLoc, 0, 1) {}
+
+ /// \brief Build an empty directive.
+ ///
+ explicit OMPOrderedDirective()
+ : OMPExecutableDirective(this, OMPOrderedDirectiveClass, OMPD_ordered,
+ 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 OMPOrderedDirective *Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ Stmt *AssociatedStmt);
+
+ /// \brief Creates an empty directive.
+ ///
+ /// \param C AST context.
+ ///
+ static OMPOrderedDirective *CreateEmpty(const ASTContext &C, EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPOrderedDirectiveClass;
+ }
+};
+
+/// \brief This represents '#pragma omp atomic' directive.
+///
+/// \code
+/// #pragma omp atomic capture
+/// \endcode
+/// In this example directive '#pragma omp atomic' has clause 'capture'.
+///
+class OMPAtomicDirective : public OMPExecutableDirective {
+ friend class ASTStmtReader;
+ /// \brief Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ /// \param NumClauses Number of clauses.
+ ///
+ OMPAtomicDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPAtomicDirectiveClass, OMPD_atomic,
+ StartLoc, EndLoc, NumClauses, 4) {}
+
+ /// \brief Build an empty directive.
+ ///
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPAtomicDirective(unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPAtomicDirectiveClass, OMPD_atomic,
+ SourceLocation(), SourceLocation(), NumClauses,
+ 4) {}
+
+ /// \brief Set 'x' part of the associated expression/statement.
+ void setX(Expr *X) { *std::next(child_begin()) = X; }
+ /// \brief Set 'v' part of the associated expression/statement.
+ void setV(Expr *V) { *std::next(child_begin(), 2) = V; }
+ /// \brief Set 'expr' part of the associated expression/statement.
+ void setExpr(Expr *E) { *std::next(child_begin(), 3) = E; }
+
+public:
+ /// \brief Creates directive with a list of \a Clauses and 'x', 'v' and 'expr'
+ /// parts of the atomic construct (see Section 2.12.6, atomic Construct, for
+ /// detailed description of 'x', 'v' and 'expr').
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param Clauses List of clauses.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ /// \param X 'x' part of the associated expression/statement.
+ /// \param V 'v' part of the associated expression/statement.
+ /// \param E 'expr' part of the associated expression/statement.
+ ///
+ static OMPAtomicDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *X, Expr *V,
+ Expr *E);
+
+ /// \brief Creates an empty directive with the place for \a NumClauses
+ /// clauses.
+ ///
+ /// \param C AST context.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPAtomicDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses, EmptyShell);
+
+ /// \brief Get 'x' part of the associated expression/statement.
+ Expr *getX() { return cast_or_null<Expr>(*std::next(child_begin())); }
+ const Expr *getX() const {
+ return cast_or_null<Expr>(*std::next(child_begin()));
+ }
+ /// \brief Get 'v' part of the associated expression/statement.
+ Expr *getV() { return cast_or_null<Expr>(*std::next(child_begin(), 2)); }
+ const Expr *getV() const {
+ return cast_or_null<Expr>(*std::next(child_begin(), 2));
+ }
+ /// \brief Get 'expr' part of the associated expression/statement.
+ Expr *getExpr() { return cast_or_null<Expr>(*std::next(child_begin(), 3)); }
+ const Expr *getExpr() const {
+ return cast_or_null<Expr>(*std::next(child_begin(), 3));
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPAtomicDirectiveClass;
+ }
+};
+
+/// \brief This represents '#pragma omp target' directive.
+///
+/// \code
+/// #pragma omp target if(a)
+/// \endcode
+/// In this example directive '#pragma omp target' has clause 'if' with
+/// condition 'a'.
+///
+class OMPTargetDirective : public OMPExecutableDirective {
+ friend class ASTStmtReader;
+ /// \brief Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ /// \param NumClauses Number of clauses.
+ ///
+ OMPTargetDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPTargetDirectiveClass, OMPD_target,
+ StartLoc, EndLoc, NumClauses, 1) {}
+
+ /// \brief Build an empty directive.
+ ///
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPTargetDirective(unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPTargetDirectiveClass, OMPD_target,
+ SourceLocation(), SourceLocation(), NumClauses,
+ 1) {}
+
+public:
+ /// \brief Creates directive with a list of \a Clauses.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param Clauses List of clauses.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ ///
+ static OMPTargetDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
+
+ /// \brief Creates an empty directive with the place for \a NumClauses
+ /// clauses.
+ ///
+ /// \param C AST context.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPTargetDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses, EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPTargetDirectiveClass;
+ }
+};
+
+/// \brief This represents '#pragma omp teams' directive.
+///
+/// \code
+/// #pragma omp teams if(a)
+/// \endcode
+/// In this example directive '#pragma omp teams' has clause 'if' with
+/// condition 'a'.
+///
+class OMPTeamsDirective : public OMPExecutableDirective {
+ friend class ASTStmtReader;
+ /// \brief Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ /// \param NumClauses Number of clauses.
+ ///
+ OMPTeamsDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPTeamsDirectiveClass, OMPD_teams,
+ StartLoc, EndLoc, NumClauses, 1) {}
+
+ /// \brief Build an empty directive.
+ ///
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPTeamsDirective(unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPTeamsDirectiveClass, OMPD_teams,
+ SourceLocation(), SourceLocation(), NumClauses,
+ 1) {}
+
+public:
+ /// \brief Creates directive with a list of \a Clauses.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param Clauses List of clauses.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ ///
+ static OMPTeamsDirective *Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt);
+
+ /// \brief Creates an empty directive with the place for \a NumClauses
+ /// clauses.
+ ///
+ /// \param C AST context.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPTeamsDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses, EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPTeamsDirectiveClass;
+ }
+};
+
} // end namespace clang
#endif
diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h
index 1026a7807a60..80b68bc0569b 100644
--- a/include/clang/AST/TemplateBase.h
+++ b/include/clang/AST/TemplateBase.h
@@ -18,8 +18,8 @@
#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/ADT/iterator_range.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
@@ -76,7 +76,7 @@ private:
struct DA {
unsigned Kind;
- bool ForRefParam;
+ void *QT;
ValueDecl *D;
};
struct I {
@@ -132,11 +132,11 @@ public:
/// \brief Construct a template argument that refers to a
/// declaration, which is either an external declaration or a
/// template declaration.
- TemplateArgument(ValueDecl *D, bool ForRefParam) {
+ TemplateArgument(ValueDecl *D, QualType QT) {
assert(D && "Expected decl");
DeclArg.Kind = Declaration;
+ DeclArg.QT = QT.getAsOpaquePtr();
DeclArg.D = D;
- DeclArg.ForRefParam = ForRefParam;
}
/// \brief Construct an integral constant template argument. The memory to
@@ -249,11 +249,9 @@ public:
return DeclArg.D;
}
- /// \brief Retrieve whether a declaration is binding to a
- /// reference parameter in a declaration non-type template argument.
- bool isDeclForReferenceParam() const {
+ QualType getParamTypeForDecl() const {
assert(getKind() == Declaration && "Unexpected kind");
- return DeclArg.ForRefParam;
+ return QualType::getFromOpaquePtr(DeclArg.QT);
}
/// \brief Retrieve the type for null non-type template argument.
@@ -344,7 +342,7 @@ public:
/// \brief Return the array of arguments in this template argument pack.
ArrayRef<TemplateArgument> getPackAsArray() const {
assert(getKind() == Pack);
- return ArrayRef<TemplateArgument>(Args.Args, Args.NumArgs);
+ return llvm::makeArrayRef(Args.Args, Args.NumArgs);
}
/// \brief Determines whether two template arguments are superficially the
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index 09862e4fb7f7..1bda01fee8ad 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -16,6 +16,7 @@
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/TemplateName.h"
+#include "clang/Basic/AddressSpaces.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/ExceptionSpecificationType.h"
#include "clang/Basic/LLVM.h"
@@ -25,11 +26,11 @@
#include "clang/Basic/Visibility.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/ADT/iterator_range.h"
#include "llvm/Support/ErrorHandling.h"
namespace clang {
@@ -400,21 +401,36 @@ public:
Mask |= qs.Mask;
}
+ /// \brief Returns true if this address space is a superset of the other one.
+ /// OpenCL v2.0 defines conversion rules (OpenCLC v2.0 s6.5.5) and notion of
+ /// overlapping address spaces.
+ /// CL1.1 or CL1.2:
+ /// every address space is a superset of itself.
+ /// CL2.0 adds:
+ /// __generic is a superset of any address space except for __constant.
+ bool isAddressSpaceSupersetOf(Qualifiers other) const {
+ return
+ // Address spaces must match exactly.
+ getAddressSpace() == other.getAddressSpace() ||
+ // Otherwise in OpenCLC v2.0 s6.5.5: every address space except
+ // for __constant can be used as __generic.
+ (getAddressSpace() == LangAS::opencl_generic &&
+ other.getAddressSpace() != LangAS::opencl_constant);
+ }
+
/// \brief Determines if these qualifiers compatibly include another set.
/// Generally this answers the question of whether an object with the other
/// qualifiers can be safely used as an object with these qualifiers.
bool compatiblyIncludes(Qualifiers other) const {
- return
- // Address spaces must match exactly.
- getAddressSpace() == other.getAddressSpace() &&
- // ObjC GC qualifiers can match, be added, or be removed, but can't be
- // changed.
- (getObjCGCAttr() == other.getObjCGCAttr() ||
- !hasObjCGCAttr() || !other.hasObjCGCAttr()) &&
- // ObjC lifetime qualifiers must match exactly.
- getObjCLifetime() == other.getObjCLifetime() &&
- // CVR qualifiers may subset.
- (((Mask & CVRMask) | (other.Mask & CVRMask)) == (Mask & CVRMask));
+ return isAddressSpaceSupersetOf(other) &&
+ // ObjC GC qualifiers can match, be added, or be removed, but can't
+ // be changed.
+ (getObjCGCAttr() == other.getObjCGCAttr() || !hasObjCGCAttr() ||
+ !other.hasObjCGCAttr()) &&
+ // ObjC lifetime qualifiers must match exactly.
+ getObjCLifetime() == other.getObjCLifetime() &&
+ // CVR qualifiers may subset.
+ (((Mask & CVRMask) | (other.Mask & CVRMask)) == (Mask & CVRMask));
}
/// \brief Determines if these qualifiers compatibly include another set of
@@ -1245,6 +1261,7 @@ protected:
class FunctionTypeBitfields {
friend class FunctionType;
+ friend class FunctionProtoType;
unsigned : NumTypeBits;
@@ -1259,6 +1276,11 @@ protected:
/// C++ 8.3.5p4: The return type, the parameter type list and the
/// cv-qualifier-seq, [...], are part of the function type.
unsigned TypeQuals : 3;
+
+ /// \brief The ref-qualifier associated with a \c FunctionProtoType.
+ ///
+ /// This is a value of type \c RefQualifierKind.
+ unsigned RefQualifier : 2;
};
class ObjCObjectTypeBitfields {
@@ -1685,6 +1707,11 @@ public:
/// type of a class template or class template partial specialization.
CXXRecordDecl *getAsCXXRecordDecl() const;
+ /// \brief Retrieves the TagDecl that this type refers to, either
+ /// because the type is a TagType or because it is the injected-class-name
+ /// type of a class template or class template partial specialization.
+ TagDecl *getAsTagDecl() const;
+
/// If this is a pointer or reference to a RecordType, return the
/// CXXRecordDecl that that type refers to.
///
@@ -1982,6 +2009,22 @@ public:
QualType getPointeeType() const { return PointeeType; }
+ /// \brief Returns true if address spaces of pointers overlap.
+ /// OpenCL v2.0 defines conversion rules for pointers to different
+ /// address spaces (OpenCLC v2.0 s6.5.5) and notion of overlapping
+ /// address spaces.
+ /// CL1.1 or CL1.2:
+ /// address spaces overlap iff they are they same.
+ /// CL2.0 adds:
+ /// __generic overlaps with any address space except for __constant.
+ bool isAddressSpaceOverlapping(const PointerType &other) const {
+ Qualifiers thisQuals = PointeeType.getQualifiers();
+ Qualifiers otherQuals = other.getPointeeType().getQualifiers();
+ // Address spaces overlap if at least one of them is a superset of another
+ return thisQuals.isAddressSpaceSupersetOf(otherQuals) ||
+ otherQuals.isAddressSpaceSupersetOf(thisQuals);
+ }
+
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
@@ -2765,7 +2808,7 @@ class FunctionType : public Type {
protected:
FunctionType(TypeClass tc, QualType res,
- unsigned typeQuals, QualType Canonical, bool Dependent,
+ QualType Canonical, bool Dependent,
bool InstantiationDependent,
bool VariablyModified, bool ContainsUnexpandedParameterPack,
ExtInfo Info)
@@ -2773,7 +2816,6 @@ protected:
ContainsUnexpandedParameterPack),
ResultType(res) {
FunctionTypeBits.ExtInfo = Info.Bits;
- FunctionTypeBits.TypeQuals = typeQuals;
}
unsigned getTypeQuals() const { return FunctionTypeBits.TypeQuals; }
@@ -2810,7 +2852,7 @@ public:
/// no information available about its arguments.
class FunctionNoProtoType : public FunctionType, public llvm::FoldingSetNode {
FunctionNoProtoType(QualType Result, QualType Canonical, ExtInfo Info)
- : FunctionType(FunctionNoProto, Result, 0, Canonical,
+ : FunctionType(FunctionNoProto, Result, Canonical,
/*Dependent=*/false, /*InstantiationDependent=*/false,
Result->isVariablyModifiedType(),
/*ContainsUnexpandedParameterPack=*/false, Info) {}
@@ -2844,33 +2886,51 @@ public:
/// type.
class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode {
public:
+ struct ExceptionSpecInfo {
+ ExceptionSpecInfo()
+ : Type(EST_None), NoexceptExpr(nullptr),
+ SourceDecl(nullptr), SourceTemplate(nullptr) {}
+
+ ExceptionSpecInfo(ExceptionSpecificationType EST)
+ : Type(EST), NoexceptExpr(nullptr), SourceDecl(nullptr),
+ SourceTemplate(nullptr) {}
+
+ /// The kind of exception specification this is.
+ ExceptionSpecificationType Type;
+ /// Explicitly-specified list of exception types.
+ ArrayRef<QualType> Exceptions;
+ /// Noexcept expression, if this is EST_ComputedNoexcept.
+ Expr *NoexceptExpr;
+ /// The function whose exception specification this is, for
+ /// EST_Unevaluated and EST_Uninstantiated.
+ FunctionDecl *SourceDecl;
+ /// The function template whose exception specification this is instantiated
+ /// from, for EST_Uninstantiated.
+ FunctionDecl *SourceTemplate;
+ };
+
/// 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(nullptr), NoexceptExpr(nullptr),
- ExceptionSpecDecl(nullptr), ExceptionSpecTemplate(nullptr),
- ConsumedParameters(nullptr) {}
+ RefQualifier(RQ_None), ConsumedParameters(nullptr) {}
ExtProtoInfo(CallingConv CC)
: ExtInfo(CC), Variadic(false), HasTrailingReturn(false), TypeQuals(0),
- ExceptionSpecType(EST_None), RefQualifier(RQ_None), NumExceptions(0),
- Exceptions(nullptr), NoexceptExpr(nullptr),
- ExceptionSpecDecl(nullptr), ExceptionSpecTemplate(nullptr),
- ConsumedParameters(nullptr) {}
+ RefQualifier(RQ_None), ConsumedParameters(nullptr) {}
+
+ ExtProtoInfo withExceptionSpec(const ExceptionSpecInfo &O) {
+ ExtProtoInfo Result(*this);
+ Result.ExceptionSpec = O;
+ return Result;
+ }
FunctionType::ExtInfo ExtInfo;
bool Variadic : 1;
bool HasTrailingReturn : 1;
unsigned char TypeQuals;
- ExceptionSpecificationType ExceptionSpecType;
RefQualifierKind RefQualifier;
- unsigned NumExceptions;
- const QualType *Exceptions;
- Expr *NoexceptExpr;
- FunctionDecl *ExceptionSpecDecl;
- FunctionDecl *ExceptionSpecTemplate;
+ ExceptionSpecInfo ExceptionSpec;
const bool *ConsumedParameters;
};
@@ -2896,7 +2956,7 @@ private:
unsigned NumExceptions : 9;
/// ExceptionSpecType - The type of exception specification this function has.
- unsigned ExceptionSpecType : 3;
+ unsigned ExceptionSpecType : 4;
/// HasAnyConsumedParams - Whether this function has any consumed parameters.
unsigned HasAnyConsumedParams : 1;
@@ -2907,11 +2967,6 @@ private:
/// HasTrailingReturn - Whether this function has a trailing return type.
unsigned HasTrailingReturn : 1;
- /// \brief The ref-qualifier associated with a \c FunctionProtoType.
- ///
- /// This is a value of type \c RefQualifierKind.
- unsigned RefQualifier : 2;
-
// ParamInfo - There is an variable size array after the class in memory that
// holds the parameter types.
@@ -2952,7 +3007,7 @@ public:
return param_type_begin()[i];
}
ArrayRef<QualType> getParamTypes() const {
- return ArrayRef<QualType>(param_type_begin(), param_type_end());
+ return llvm::makeArrayRef(param_type_begin(), param_type_end());
}
ExtProtoInfo getExtProtoInfo() const {
@@ -2960,19 +3015,18 @@ public:
EPI.ExtInfo = getExtInfo();
EPI.Variadic = isVariadic();
EPI.HasTrailingReturn = hasTrailingReturn();
- EPI.ExceptionSpecType = getExceptionSpecType();
+ EPI.ExceptionSpec.Type = getExceptionSpecType();
EPI.TypeQuals = static_cast<unsigned char>(getTypeQuals());
EPI.RefQualifier = getRefQualifier();
- if (EPI.ExceptionSpecType == EST_Dynamic) {
- EPI.NumExceptions = NumExceptions;
- EPI.Exceptions = exception_begin();
- } else if (EPI.ExceptionSpecType == EST_ComputedNoexcept) {
- EPI.NoexceptExpr = getNoexceptExpr();
- } else if (EPI.ExceptionSpecType == EST_Uninstantiated) {
- EPI.ExceptionSpecDecl = getExceptionSpecDecl();
- EPI.ExceptionSpecTemplate = getExceptionSpecTemplate();
- } else if (EPI.ExceptionSpecType == EST_Unevaluated) {
- EPI.ExceptionSpecDecl = getExceptionSpecDecl();
+ if (EPI.ExceptionSpec.Type == EST_Dynamic) {
+ EPI.ExceptionSpec.Exceptions = exceptions();
+ } else if (EPI.ExceptionSpec.Type == EST_ComputedNoexcept) {
+ EPI.ExceptionSpec.NoexceptExpr = getNoexceptExpr();
+ } else if (EPI.ExceptionSpec.Type == EST_Uninstantiated) {
+ EPI.ExceptionSpec.SourceDecl = getExceptionSpecDecl();
+ EPI.ExceptionSpec.SourceTemplate = getExceptionSpecTemplate();
+ } else if (EPI.ExceptionSpec.Type == EST_Unevaluated) {
+ EPI.ExceptionSpec.SourceDecl = getExceptionSpecDecl();
}
if (hasAnyConsumedParams())
EPI.ConsumedParameters = getConsumedParamsBuffer();
@@ -2995,6 +3049,8 @@ public:
bool hasNoexceptExceptionSpec() const {
return isNoexceptExceptionSpec(getExceptionSpecType());
}
+ /// \brief Return whether this function has a dependent exception spec.
+ bool hasDependentExceptionSpec() const;
/// \brief Result type of getNoexceptSpec().
enum NoexceptResult {
NR_NoNoexcept, ///< There is no noexcept specifier.
@@ -3057,7 +3113,7 @@ public:
/// \brief Retrieve the ref-qualifier associated with this function type.
RefQualifierKind getRefQualifier() const {
- return static_cast<RefQualifierKind>(RefQualifier);
+ return static_cast<RefQualifierKind>(FunctionTypeBits.RefQualifier);
}
typedef const QualType *param_type_iterator;
@@ -3074,10 +3130,9 @@ public:
}
typedef const QualType *exception_iterator;
- typedef llvm::iterator_range<exception_iterator> exception_range;
- exception_range exceptions() const {
- return exception_range(exception_begin(), exception_end());
+ ArrayRef<QualType> exceptions() const {
+ return llvm::makeArrayRef(exception_begin(), exception_end());
}
exception_iterator exception_begin() const {
// exceptions begin where arguments end
@@ -3416,6 +3471,7 @@ public:
attr_stdcall,
attr_thiscall,
attr_pascal,
+ attr_vectorcall,
attr_pnaclcall,
attr_inteloclbicc,
attr_ms_abi,
@@ -5231,8 +5287,8 @@ template <typename T> const T *Type::castAs() const {
ArrayType_cannot_be_used_with_getAs<T> at;
(void) at;
- assert(isa<T>(CanonicalType));
if (const T *ty = dyn_cast<T>(this)) return ty;
+ assert(isa<T>(CanonicalType));
return cast<T>(getUnqualifiedDesugaredType());
}
diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h
index 3648d2a5c259..4f3c811ce275 100644
--- a/include/clang/AST/TypeLoc.h
+++ b/include/clang/AST/TypeLoc.h
@@ -1208,7 +1208,7 @@ public:
}
ArrayRef<ParmVarDecl *> getParams() const {
- return ArrayRef<ParmVarDecl *>(getParmArray(), getNumParams());
+ return llvm::makeArrayRef(getParmArray(), getNumParams());
}
// ParmVarDecls* are stored after Info, one for each parameter.
@@ -1567,6 +1567,8 @@ public:
void setUnderlyingTInfo(TypeSourceInfo* TI) const {
this->getLocalData()->UnderlyingTInfo = TI;
}
+
+ void initializeLocal(ASTContext &Context, SourceLocation Loc);
};
// FIXME: location of the 'decltype' and parens.
diff --git a/include/clang/AST/TypeOrdering.h b/include/clang/AST/TypeOrdering.h
index 9c9f15e95323..392e544d90c1 100644
--- a/include/clang/AST/TypeOrdering.h
+++ b/include/clang/AST/TypeOrdering.h
@@ -16,8 +16,8 @@
///
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_TYPE_ORDERING_H
-#define LLVM_CLANG_TYPE_ORDERING_H
+#ifndef LLVM_CLANG_AST_TYPEORDERING_H
+#define LLVM_CLANG_AST_TYPEORDERING_H
#include "clang/AST/CanonicalType.h"
#include "clang/AST/Type.h"
diff --git a/include/clang/AST/UnresolvedSet.h b/include/clang/AST/UnresolvedSet.h
index 2ef5800c305f..a11f22d201b7 100644
--- a/include/clang/AST/UnresolvedSet.h
+++ b/include/clang/AST/UnresolvedSet.h
@@ -98,7 +98,7 @@ class UnresolvedSetImpl {
private:
template <unsigned N> friend class UnresolvedSet;
UnresolvedSetImpl() {}
- UnresolvedSetImpl(const UnresolvedSetImpl &) LLVM_DELETED_FUNCTION;
+ UnresolvedSetImpl(const UnresolvedSetImpl &) {}
public:
// We don't currently support assignment through this iterator, so we might
diff --git a/include/clang/ASTMatchers/ASTMatchFinder.h b/include/clang/ASTMatchers/ASTMatchFinder.h
index 8af0546db57b..ce2674e442da 100644
--- a/include/clang/ASTMatchers/ASTMatchFinder.h
+++ b/include/clang/ASTMatchers/ASTMatchFinder.h
@@ -38,10 +38,12 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCH_FINDER_H
-#define LLVM_CLANG_AST_MATCHERS_AST_MATCH_FINDER_H
+#ifndef LLVM_CLANG_ASTMATCHERS_ASTMATCHFINDER_H
+#define LLVM_CLANG_ASTMATCHERS_ASTMATCHFINDER_H
#include "clang/ASTMatchers/ASTMatchers.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/Timer.h"
namespace clang {
@@ -102,6 +104,12 @@ public:
///
/// Optionally override to do per translation unit tasks.
virtual void onEndOfTranslationUnit() {}
+
+ /// \brief An id used to group the matchers.
+ ///
+ /// This id is used, for example, for the profiling output.
+ /// It defaults to "<unknown>".
+ virtual StringRef getID() const;
};
/// \brief Called when parsing is finished. Intended for testing only.
@@ -111,7 +119,22 @@ public:
virtual void run() = 0;
};
- MatchFinder();
+ struct MatchFinderOptions {
+ struct Profiling {
+ Profiling(llvm::StringMap<llvm::TimeRecord> &Records)
+ : Records(Records) {}
+
+ /// \brief Per bucket timing information.
+ llvm::StringMap<llvm::TimeRecord> &Records;
+ };
+
+ /// \brief Enables per-check timers.
+ ///
+ /// It prints a report after match.
+ llvm::Optional<Profiling> CheckProfiling;
+ };
+
+ MatchFinder(MatchFinderOptions Options = MatchFinderOptions());
~MatchFinder();
/// \brief Adds a matcher to execute when running over the AST.
@@ -148,7 +171,7 @@ public:
MatchCallback *Action);
/// \brief Creates a clang ASTConsumer that finds all matches.
- clang::ASTConsumer *newASTConsumer();
+ std::unique_ptr<clang::ASTConsumer> newASTConsumer();
/// \brief Calls the registered callbacks on all matches on the given \p Node.
///
@@ -173,11 +196,25 @@ public:
/// Each call to FindAll(...) will call the closure once.
void registerTestCallbackAfterParsing(ParsingDoneTestCallback *ParsingDone);
-private:
- /// \brief For each \c DynTypedMatcher a \c MatchCallback that will be called
+ /// \brief For each \c Matcher<> a \c MatchCallback that will be called
/// when it matches.
- std::vector<std::pair<internal::DynTypedMatcher, MatchCallback *> >
- MatcherCallbackPairs;
+ struct MatchersByType {
+ std::vector<std::pair<internal::DynTypedMatcher, MatchCallback *>>
+ DeclOrStmt;
+ std::vector<std::pair<TypeMatcher, MatchCallback *>> Type;
+ std::vector<std::pair<NestedNameSpecifierMatcher, MatchCallback *>>
+ NestedNameSpecifier;
+ std::vector<std::pair<NestedNameSpecifierLocMatcher, MatchCallback *>>
+ NestedNameSpecifierLoc;
+ std::vector<std::pair<TypeLocMatcher, MatchCallback *>> TypeLoc;
+ /// \brief All the callbacks in one container to simplify iteration.
+ std::vector<MatchCallback *> AllCallbacks;
+ };
+
+private:
+ MatchersByType Matchers;
+
+ MatchFinderOptions Options;
/// \brief Called when parsing is done.
ParsingDoneTestCallback *ParsingDone;
@@ -210,16 +247,14 @@ match(MatcherT Matcher, const ast_type_traits::DynTypedNode &Node,
///
/// This is useful in combanation with \c match():
/// \code
-/// Decl *D = selectFirst<Decl>("id", match(Matcher.bind("id"),
-/// Node, Context));
+/// const Decl *D = selectFirst<Decl>("id", match(Matcher.bind("id"),
+/// Node, Context));
/// \endcode
template <typename NodeT>
-NodeT *
+const NodeT *
selectFirst(StringRef BoundTo, const SmallVectorImpl<BoundNodes> &Results) {
- for (SmallVectorImpl<BoundNodes>::const_iterator I = Results.begin(),
- E = Results.end();
- I != E; ++I) {
- if (NodeT *Node = I->getNodeAs<NodeT>(BoundTo))
+ for (const BoundNodes &N : Results) {
+ if (const NodeT *Node = N.getNodeAs<NodeT>(BoundTo))
return Node;
}
return nullptr;
@@ -243,7 +278,7 @@ match(MatcherT Matcher, const ast_type_traits::DynTypedNode &Node,
MatchFinder Finder;
Finder.addMatcher(Matcher, &Callback);
Finder.match(Node, Context);
- return Callback.Nodes;
+ return std::move(Callback.Nodes);
}
template <typename MatcherT, typename NodeT>
@@ -255,4 +290,4 @@ match(MatcherT Matcher, const NodeT &Node, ASTContext &Context) {
} // end namespace ast_matchers
} // end namespace clang
-#endif // LLVM_CLANG_AST_MATCHERS_AST_MATCH_FINDER_H
+#endif
diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h
index 1ff4ab367fd5..f002cb9cbaba 100644
--- a/include/clang/ASTMatchers/ASTMatchers.h
+++ b/include/clang/ASTMatchers/ASTMatchers.h
@@ -42,9 +42,10 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_H
-#define LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_H
+#ifndef LLVM_CLANG_ASTMATCHERS_ASTMATCHERS_H
+#define LLVM_CLANG_ASTMATCHERS_ASTMATCHERS_H
+#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/ASTMatchers/ASTMatchersInternal.h"
@@ -140,9 +141,97 @@ typedef internal::Matcher<NestedNameSpecifierLoc> NestedNameSpecifierLocMatcher;
/// \endcode
///
/// Usable as: Any Matcher
-inline internal::PolymorphicMatcherWithParam0<internal::TrueMatcher>
-anything() {
- return internal::PolymorphicMatcherWithParam0<internal::TrueMatcher>();
+inline internal::TrueMatcher anything() { return internal::TrueMatcher(); }
+
+/// \brief Matches typedef declarations.
+///
+/// Given
+/// \code
+/// typedef int X;
+/// \endcode
+/// typedefDecl()
+/// matches "typedef int X"
+const internal::VariadicDynCastAllOfMatcher<Decl, TypedefDecl> typedefDecl;
+
+/// \brief Matches AST nodes that were expanded within the main-file.
+///
+/// Example matches X but not Y (matcher = recordDecl(isExpansionInMainFile())
+/// \code
+/// #include <Y.h>
+/// class X {};
+/// \endcode
+/// Y.h:
+/// \code
+/// class Y {};
+/// \endcode
+///
+/// Usable as: Matcher<Decl>, Matcher<Stmt>, Matcher<TypeLoc>
+AST_POLYMORPHIC_MATCHER(isExpansionInMainFile,
+ AST_POLYMORPHIC_SUPPORTED_TYPES_3(Decl, Stmt,
+ TypeLoc)) {
+ auto &SourceManager = Finder->getASTContext().getSourceManager();
+ return SourceManager.isInMainFile(
+ SourceManager.getExpansionLoc(Node.getLocStart()));
+}
+
+/// \brief Matches AST nodes that were expanded within system-header-files.
+///
+/// Example matches Y but not X
+/// (matcher = recordDecl(isExpansionInSystemHeader())
+/// \code
+/// #include <SystemHeader.h>
+/// class X {};
+/// \endcode
+/// SystemHeader.h:
+/// \code
+/// class Y {};
+/// \endcode
+///
+/// Usable as: Matcher<Decl>, Matcher<Stmt>, Matcher<TypeLoc>
+AST_POLYMORPHIC_MATCHER(isExpansionInSystemHeader,
+ AST_POLYMORPHIC_SUPPORTED_TYPES_3(Decl, Stmt,
+ TypeLoc)) {
+ auto &SourceManager = Finder->getASTContext().getSourceManager();
+ auto ExpansionLoc = SourceManager.getExpansionLoc(Node.getLocStart());
+ if (ExpansionLoc.isInvalid()) {
+ return false;
+ }
+ return SourceManager.isInSystemHeader(ExpansionLoc);
+}
+
+/// \brief Matches AST nodes that were expanded within files whose name is
+/// partially matching a given regex.
+///
+/// Example matches Y but not X
+/// (matcher = recordDecl(isExpansionInFileMatching("AST.*"))
+/// \code
+/// #include "ASTMatcher.h"
+/// class X {};
+/// \endcode
+/// ASTMatcher.h:
+/// \code
+/// class Y {};
+/// \endcode
+///
+/// Usable as: Matcher<Decl>, Matcher<Stmt>, Matcher<TypeLoc>
+AST_POLYMORPHIC_MATCHER_P(isExpansionInFileMatching,
+ AST_POLYMORPHIC_SUPPORTED_TYPES_3(Decl, Stmt,
+ TypeLoc),
+ std::string, RegExp) {
+ auto &SourceManager = Finder->getASTContext().getSourceManager();
+ auto ExpansionLoc = SourceManager.getExpansionLoc(Node.getLocStart());
+ if (ExpansionLoc.isInvalid()) {
+ return false;
+ }
+ auto FileEntry =
+ SourceManager.getFileEntryForID(SourceManager.getFileID(ExpansionLoc));
+ if (!FileEntry) {
+ return false;
+ }
+
+ auto Filename = FileEntry->getName();
+ llvm::Regex RE(RegExp);
+ return RE.match(Filename);
}
/// \brief Matches declarations.
@@ -156,6 +245,17 @@ anything() {
/// \endcode
const internal::VariadicAllOfMatcher<Decl> decl;
+/// \brief Matches a declaration of a linkage specification.
+///
+/// Given
+/// \code
+/// extern "C" {}
+/// \endcode
+/// linkageSpecDecl()
+/// matches "extern "C" {}"
+const internal::VariadicDynCastAllOfMatcher<Decl, LinkageSpecDecl>
+ linkageSpecDecl;
+
/// \brief Matches a declaration of anything that could have a name.
///
/// Example matches \c X, \c S, the anonymous union type, \c i, and \c U;
@@ -263,6 +363,17 @@ const internal::VariadicDynCastAllOfMatcher<
/// \endcode
const internal::VariadicAllOfMatcher<CXXCtorInitializer> ctorInitializer;
+/// \brief Matches template arguments.
+///
+/// Given
+/// \code
+/// template <typename T> struct C {};
+/// C<int> c;
+/// \endcode
+/// templateArgument()
+/// matches 'int' in C<int>.
+const internal::VariadicAllOfMatcher<TemplateArgument> templateArgument;
+
/// \brief Matches public C++ declarations.
///
/// Given
@@ -441,6 +552,23 @@ AST_POLYMORPHIC_MATCHER_P2(
return InnerMatcher.matches(List[N], Finder, Builder);
}
+/// \brief Matches if the number of template arguments equals \p N.
+///
+/// Given
+/// \code
+/// template<typename T> struct C {};
+/// C<int> c;
+/// \endcode
+/// classTemplateSpecializationDecl(templateArgumentCountIs(1))
+/// matches C<int>.
+AST_POLYMORPHIC_MATCHER_P(
+ templateArgumentCountIs,
+ AST_POLYMORPHIC_SUPPORTED_TYPES_2(ClassTemplateSpecializationDecl,
+ TemplateSpecializationType),
+ unsigned, N) {
+ return internal::getTemplateSpecializationArgs(Node).size() == N;
+}
+
/// \brief Matches a TemplateArgument that refers to a certain type.
///
/// Given
@@ -497,6 +625,68 @@ AST_MATCHER_P(TemplateArgument, isExpr, internal::Matcher<Expr>, InnerMatcher) {
return false;
}
+/// \brief Matches a TemplateArgument that is an integral value.
+///
+/// Given
+/// \code
+/// template<int T> struct A {};
+/// C<42> c;
+/// \endcode
+/// classTemplateSpecializationDecl(
+/// hasAnyTemplateArgument(isIntegral()))
+/// matches the implicit instantiation of C in C<42>
+/// with isIntegral() matching 42.
+AST_MATCHER(TemplateArgument, isIntegral) {
+ return Node.getKind() == TemplateArgument::Integral;
+}
+
+/// \brief Matches a TemplateArgument that referes to an integral type.
+///
+/// Given
+/// \code
+/// template<int T> struct A {};
+/// C<42> c;
+/// \endcode
+/// classTemplateSpecializationDecl(
+/// hasAnyTemplateArgument(refersToIntegralType(asString("int"))))
+/// matches the implicit instantiation of C in C<42>.
+AST_MATCHER_P(TemplateArgument, refersToIntegralType,
+ internal::Matcher<QualType>, InnerMatcher) {
+ if (Node.getKind() != TemplateArgument::Integral)
+ return false;
+ return InnerMatcher.matches(Node.getIntegralType(), Finder, Builder);
+}
+
+/// \brief Matches a TemplateArgument of integral type with a given value.
+///
+/// Note that 'Value' is a string as the template argument's value is
+/// an arbitrary precision integer. 'Value' must be euqal to the canonical
+/// representation of that integral value in base 10.
+///
+/// Given
+/// \code
+/// template<int T> struct A {};
+/// C<42> c;
+/// \endcode
+/// classTemplateSpecializationDecl(
+/// hasAnyTemplateArgument(equalsIntegralValue("42")))
+/// matches the implicit instantiation of C in C<42>.
+AST_MATCHER_P(TemplateArgument, equalsIntegralValue,
+ std::string, Value) {
+ if (Node.getKind() != TemplateArgument::Integral)
+ return false;
+ return Node.getAsIntegral().toString(10) == Value;
+}
+
+/// \brief Matches any value declaration.
+///
+/// Example matches A, B, C and F
+/// \code
+/// enum X { A, B, C };
+/// void F();
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<Decl, ValueDecl> valueDecl;
+
/// \brief Matches C++ constructor declarations.
///
/// Example matches Foo::Foo() and Foo::Foo(int)
@@ -1414,21 +1604,21 @@ const internal::VariadicAllOfMatcher<TypeLoc> typeLoc;
///
/// Usable as: Any Matcher
const internal::VariadicOperatorMatcherFunc<2, UINT_MAX> eachOf = {
- internal::EachOfVariadicOperator
+ internal::DynTypedMatcher::VO_EachOf
};
/// \brief Matches if any of the given matchers matches.
///
/// Usable as: Any Matcher
const internal::VariadicOperatorMatcherFunc<2, UINT_MAX> anyOf = {
- internal::AnyOfVariadicOperator
+ internal::DynTypedMatcher::VO_AnyOf
};
/// \brief Matches if all given matchers match.
///
/// Usable as: Any Matcher
const internal::VariadicOperatorMatcherFunc<2, UINT_MAX> allOf = {
- internal::AllOfVariadicOperator
+ internal::DynTypedMatcher::VO_AllOf
};
/// \brief Matches sizeof (C99), alignof (C++11) and vec_step (OpenCL)
@@ -1502,16 +1692,8 @@ inline internal::Matcher<Stmt> sizeOfExpr(
/// \code
/// namespace a { namespace b { class X; } }
/// \endcode
-AST_MATCHER_P(NamedDecl, hasName, std::string, Name) {
- assert(!Name.empty());
- const std::string FullNameString = "::" + Node.getQualifiedNameAsString();
- const StringRef FullName = FullNameString;
- const StringRef Pattern = Name;
- if (Pattern.startswith("::")) {
- return FullName == Pattern;
- } else {
- return FullName.endswith(("::" + Pattern).str());
- }
+inline internal::Matcher<NamedDecl> hasName(const std::string &Name) {
+ return internal::Matcher<NamedDecl>(new internal::HasNameMatcher(Name));
}
/// \brief Matches NamedDecl nodes whose fully qualified names contain
@@ -1558,7 +1740,7 @@ AST_MATCHER_P(NamedDecl, matchesName, std::string, RegExp) {
inline internal::PolymorphicMatcherWithParam1<
internal::HasOverloadedOperatorNameMatcher, StringRef,
AST_POLYMORPHIC_SUPPORTED_TYPES_2(CXXOperatorCallExpr, FunctionDecl)>
-hasOverloadedOperatorName(const StringRef Name) {
+hasOverloadedOperatorName(StringRef Name) {
return internal::PolymorphicMatcherWithParam1<
internal::HasOverloadedOperatorNameMatcher, StringRef,
AST_POLYMORPHIC_SUPPORTED_TYPES_2(CXXOperatorCallExpr, FunctionDecl)>(
@@ -1592,7 +1774,7 @@ AST_MATCHER_P(CXXRecordDecl, isDerivedFrom,
}
/// \brief Overloaded method as shortcut for \c isDerivedFrom(hasName(...)).
-AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isDerivedFrom, StringRef, BaseName, 1) {
+AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isDerivedFrom, std::string, BaseName, 1) {
assert(!BaseName.empty());
return isDerivedFrom(hasName(BaseName)).matches(Node, Finder, Builder);
}
@@ -1607,8 +1789,8 @@ AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isSameOrDerivedFrom,
/// \brief Overloaded method as shortcut for
/// \c isSameOrDerivedFrom(hasName(...)).
-AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isSameOrDerivedFrom, StringRef, BaseName,
- 1) {
+AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isSameOrDerivedFrom, std::string,
+ BaseName, 1) {
assert(!BaseName.empty());
return isSameOrDerivedFrom(hasName(BaseName)).matches(Node, Finder, Builder);
}
@@ -1768,7 +1950,7 @@ const internal::ArgumentAdaptingMatcherFunc<
///
/// Usable as: Any Matcher
const internal::VariadicOperatorMatcherFunc<1, 1> unless = {
- internal::NotUnaryOperator
+ internal::DynTypedMatcher::VO_UnaryNot
};
/// \brief Matches a node if the declaration associated with that node
@@ -1844,7 +2026,7 @@ AST_MATCHER_P(CallExpr, callee, internal::Matcher<Stmt>,
/// Example matches y.x() (matcher = callExpr(callee(methodDecl(hasName("x")))))
/// \code
/// class Y { public: void x(); };
-/// void z() { Y y; y.x();
+/// void z() { Y y; y.x(); }
/// \endcode
AST_MATCHER_P_OVERLOAD(CallExpr, callee, internal::Matcher<Decl>, InnerMatcher,
1) {
@@ -1952,6 +2134,7 @@ AST_MATCHER_P_OVERLOAD(QualType, pointsTo, internal::Matcher<Decl>,
/// void a(X b) {
/// X &x = b;
/// const X &y = b;
+/// }
/// };
/// \endcode
AST_MATCHER_P(QualType, references, internal::Matcher<QualType>,
@@ -2280,11 +2463,10 @@ AST_MATCHER(CXXCtorInitializer, isWritten) {
AST_POLYMORPHIC_MATCHER_P(hasAnyArgument, AST_POLYMORPHIC_SUPPORTED_TYPES_2(
CallExpr, CXXConstructExpr),
internal::Matcher<Expr>, InnerMatcher) {
- for (unsigned I = 0; I < Node.getNumArgs(); ++I) {
+ for (const Expr *Arg : Node.arguments()) {
BoundNodesTreeBuilder Result(*Builder);
- if (InnerMatcher.matches(*Node.getArg(I)->IgnoreParenImpCasts(), Finder,
- &Result)) {
- *Builder = Result;
+ if (InnerMatcher.matches(*Arg->IgnoreParenImpCasts(), Finder, &Result)) {
+ *Builder = std::move(Result);
return true;
}
}
@@ -2372,6 +2554,19 @@ AST_MATCHER(FunctionDecl, isExternC) {
return Node.isExternC();
}
+/// \brief Matches deleted function declarations.
+///
+/// Given:
+/// \code
+/// void Func();
+/// void DeletedFunc() = delete;
+/// \endcode
+/// functionDecl(isDeleted())
+/// matches the declaration of DeletedFunc, but not Func.
+AST_MATCHER(FunctionDecl, isDeleted) {
+ return Node.isDeleted();
+}
+
/// \brief Matches the condition expression of an if statement, for loop,
/// or conditional operator.
///
@@ -2953,6 +3148,43 @@ AST_POLYMORPHIC_MATCHER(
TSK_ExplicitInstantiationDefinition);
}
+/// \brief Matches declarations that are template instantiations or are inside
+/// template instantiations.
+///
+/// Given
+/// \code
+/// template<typename T> void A(T t) { T i; }
+/// A(0);
+/// A(0U);
+/// \endcode
+/// functionDecl(isInstantiated())
+/// matches 'A(int) {...};' and 'A(unsigned) {...}'.
+AST_MATCHER_FUNCTION(internal::Matcher<Decl>, isInstantiated) {
+ auto IsInstantiation = decl(anyOf(recordDecl(isTemplateInstantiation()),
+ functionDecl(isTemplateInstantiation())));
+ return decl(anyOf(IsInstantiation, hasAncestor(IsInstantiation)));
+}
+
+/// \brief Matches statements inside of a template instantiation.
+///
+/// Given
+/// \code
+/// int j;
+/// template<typename T> void A(T t) { T i; j += 42;}
+/// A(0);
+/// A(0U);
+/// \endcode
+/// declStmt(isInTemplateInstantiation())
+/// matches 'int i;' and 'unsigned i'.
+/// unless(stmt(isInTemplateInstantiation()))
+/// will NOT match j += 42; as it's shared between the template definition and
+/// instantiation.
+AST_MATCHER_FUNCTION(internal::Matcher<Stmt>, isInTemplateInstantiation) {
+ return stmt(
+ hasAncestor(decl(anyOf(recordDecl(isTemplateInstantiation()),
+ functionDecl(isTemplateInstantiation())))));
+}
+
/// \brief Matches explicit template specializations of function, class, or
/// static member variable template instantiations.
///
@@ -2979,6 +3211,18 @@ AST_MATCHER_FUNCTION_P_OVERLOAD(internal::BindableMatcher<TypeLoc>, loc,
new internal::TypeLocTypeMatcher(InnerMatcher));
}
+/// \brief Matches type \c void.
+///
+/// Given
+/// \code
+/// struct S { void func(); };
+/// \endcode
+/// functionDecl(returns(voidType()))
+/// matches "void func();"
+AST_MATCHER(Type, voidType) {
+ return Node.isVoidType();
+}
+
/// \brief Matches builtin Types.
///
/// Given
@@ -3094,6 +3338,7 @@ AST_TYPE_MATCHER(IncompleteArrayType, incompleteArrayType);
/// int a[] = { 2, 3 }
/// int b[42];
/// int c[a[0]];
+/// }
/// \endcode
/// variableArrayType()
/// matches "int c[a[0]]"
@@ -3432,8 +3677,9 @@ AST_MATCHER_P(ElaboratedType, namesType, internal::Matcher<QualType>,
/// \c recordDecl(hasDeclContext(namedDecl(hasName("M")))) matches the
/// declaration of \c class \c D.
AST_MATCHER_P(Decl, hasDeclContext, internal::Matcher<Decl>, InnerMatcher) {
- return InnerMatcher.matches(*Decl::castFromDeclContext(Node.getDeclContext()),
- Finder, Builder);
+ const DeclContext *DC = Node.getDeclContext();
+ if (!DC) return false;
+ return InnerMatcher.matches(*Decl::castFromDeclContext(DC), Finder, Builder);
}
/// \brief Matches nested name specifiers.
@@ -3599,7 +3845,7 @@ AST_MATCHER_P(SwitchStmt, forEachSwitchCase, internal::Matcher<SwitchCase>,
Result.addMatch(CaseBuilder);
}
}
- *Builder = Result;
+ *Builder = std::move(Result);
return Matched;
}
@@ -3622,7 +3868,7 @@ AST_MATCHER_P(CXXConstructorDecl, forEachConstructorInitializer,
Result.addMatch(InitBuilder);
}
}
- *Builder = Result;
+ *Builder = std::move(Result);
return Matched;
}
@@ -3643,7 +3889,32 @@ AST_MATCHER_P(CaseStmt, hasCaseConstant, internal::Matcher<Expr>,
return InnerMatcher.matches(*Node.getLHS(), Finder, Builder);
}
+/// \brief Matches declaration that has a given attribute.
+///
+/// Given
+/// \code
+/// __attribute__((device)) void f() { ... }
+/// \endcode
+/// decl(hasAttr(clang::attr::CUDADevice)) matches the function declaration of
+/// f.
+AST_MATCHER_P(Decl, hasAttr, attr::Kind, AttrKind) {
+ for (const auto *Attr : Node.attrs()) {
+ if (Attr->getKind() == AttrKind)
+ return true;
+ }
+ return false;
+}
+
+/// \brief Matches CUDA kernel call expression.
+///
+/// Example matches,
+/// \code
+/// kernel<<<i,j>>>();
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<Stmt, CUDAKernelCallExpr>
+ CUDAKernelCallExpr;
+
} // end namespace ast_matchers
} // end namespace clang
-#endif // LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_H
+#endif
diff --git a/include/clang/ASTMatchers/ASTMatchersInternal.h b/include/clang/ASTMatchers/ASTMatchersInternal.h
index 94435fd274eb..ebe5cddb622a 100644
--- a/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ b/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -32,8 +32,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_INTERNAL_H
-#define LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_INTERNAL_H
+#ifndef LLVM_CLANG_ASTMATCHERS_ASTMATCHERSINTERNAL_H
+#define LLVM_CLANG_ASTMATCHERS_ASTMATCHERSINTERNAL_H
#include "clang/AST/ASTTypeTraits.h"
#include "clang/AST/Decl.h"
@@ -44,6 +44,7 @@
#include "clang/AST/Type.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/VariadicFunction.h"
+#include "llvm/Support/ManagedStatic.h"
#include <map>
#include <string>
#include <vector>
@@ -61,9 +62,8 @@ public:
/// \brief Adds \c Node to the map with key \c ID.
///
/// The node's base type should be in NodeBaseType or it will be unaccessible.
- template <typename T>
- void addNode(StringRef ID, const T* Node) {
- NodeMap[ID] = ast_type_traits::DynTypedNode::create(*Node);
+ void addNode(StringRef ID, const ast_type_traits::DynTypedNode& DynNode) {
+ NodeMap[ID] = DynNode;
}
/// \brief Returns the AST node bound to \c ID.
@@ -103,6 +103,16 @@ public:
return NodeMap;
}
+ /// \brief Returns \c true if this \c BoundNodesMap can be compared, i.e. all
+ /// stored nodes have memoization data.
+ bool isComparable() const {
+ for (const auto &IDAndNode : NodeMap) {
+ if (!IDAndNode.second.getMemoizationData())
+ return false;
+ }
+ return true;
+ }
+
private:
IDToNodeMap NodeMap;
};
@@ -126,11 +136,12 @@ public:
};
/// \brief Add a binding from an id to a node.
- template <typename T> void setBinding(const std::string &Id, const T *Node) {
+ void setBinding(const std::string &Id,
+ const ast_type_traits::DynTypedNode &DynNode) {
if (Bindings.empty())
Bindings.push_back(BoundNodesMap());
- for (unsigned i = 0, e = Bindings.size(); i != e; ++i)
- Bindings[i].addNode(Id, Node);
+ for (BoundNodesMap &Binding : Bindings)
+ Binding.addNode(Id, DynNode);
}
/// \brief Adds a branch in the tree.
@@ -153,12 +164,38 @@ public:
return Bindings < Other.Bindings;
}
+ /// \brief Returns \c true if this \c BoundNodesTreeBuilder can be compared,
+ /// i.e. all stored node maps have memoization data.
+ bool isComparable() const {
+ for (const BoundNodesMap &NodesMap : Bindings) {
+ if (!NodesMap.isComparable())
+ return false;
+ }
+ return true;
+ }
+
private:
SmallVector<BoundNodesMap, 16> Bindings;
};
class ASTMatchFinder;
+/// \brief Generic interface for all matchers.
+///
+/// Used by the implementation of Matcher<T> and DynTypedMatcher.
+/// In general, implement MatcherInterface<T> or SingleNodeMatcherInterface<T>
+/// instead.
+class DynMatcherInterface : public RefCountedBaseVPTR {
+public:
+ /// \brief Returns true if \p DynNode can be matched.
+ ///
+ /// May bind \p DynNode to an ID via \p Builder, or recurse into
+ /// the AST via \p Finder.
+ virtual bool dynMatches(const ast_type_traits::DynTypedNode &DynNode,
+ ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const = 0;
+};
+
/// \brief Generic interface for matchers on an AST node of type T.
///
/// Implement this if your matcher may need to inspect the children or
@@ -167,7 +204,7 @@ class ASTMatchFinder;
/// current node and doesn't care about its children or descendants,
/// implement SingleNodeMatcherInterface instead.
template <typename T>
-class MatcherInterface : public RefCountedBaseVPTR {
+class MatcherInterface : public DynMatcherInterface {
public:
virtual ~MatcherInterface() {}
@@ -178,6 +215,12 @@ public:
virtual bool matches(const T &Node,
ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const = 0;
+
+ bool dynMatches(const ast_type_traits::DynTypedNode &DynNode,
+ ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const override {
+ return matches(DynNode.getUnchecked<T>(), Finder, Builder);
+ }
};
/// \brief Interface for matchers that only evaluate properties on a single
@@ -199,6 +242,145 @@ private:
}
};
+template <typename> class Matcher;
+
+/// \brief Matcher that works on a \c DynTypedNode.
+///
+/// It is constructed from a \c Matcher<T> object and redirects most calls to
+/// underlying matcher.
+/// It checks whether the \c DynTypedNode is convertible into the type of the
+/// underlying matcher and then do the actual match on the actual node, or
+/// return false if it is not convertible.
+class DynTypedMatcher {
+public:
+ /// \brief Takes ownership of the provided implementation pointer.
+ template <typename T>
+ DynTypedMatcher(MatcherInterface<T> *Implementation)
+ : AllowBind(false),
+ SupportedKind(ast_type_traits::ASTNodeKind::getFromNodeKind<T>()),
+ RestrictKind(SupportedKind), Implementation(Implementation) {}
+
+ /// \brief Construct from a variadic function.
+ enum VariadicOperator {
+ /// \brief Matches nodes for which all provided matchers match.
+ VO_AllOf,
+ /// \brief Matches nodes for which at least one of the provided matchers
+ /// matches.
+ VO_AnyOf,
+ /// \brief Matches nodes for which at least one of the provided matchers
+ /// matches, but doesn't stop at the first match.
+ VO_EachOf,
+ /// \brief Matches nodes that do not match the provided matcher.
+ ///
+ /// Uses the variadic matcher interface, but fails if
+ /// InnerMatchers.size() != 1.
+ VO_UnaryNot
+ };
+ static DynTypedMatcher
+ constructVariadic(VariadicOperator Op,
+ std::vector<DynTypedMatcher> InnerMatchers);
+
+ /// \brief Get a "true" matcher for \p NodeKind.
+ ///
+ /// It only checks that the node is of the right kind.
+ static DynTypedMatcher trueMatcher(ast_type_traits::ASTNodeKind NodeKind);
+
+ void setAllowBind(bool AB) { AllowBind = AB; }
+
+ /// \brief Check whether this matcher could ever match a node of kind \p Kind.
+ /// \return \c false if this matcher will never match such a node. Otherwise,
+ /// return \c true.
+ bool canMatchNodesOfKind(ast_type_traits::ASTNodeKind Kind) const;
+
+ /// \brief Return a matcher that points to the same implementation, but
+ /// restricts the node types for \p Kind.
+ DynTypedMatcher dynCastTo(const ast_type_traits::ASTNodeKind Kind) const;
+
+ /// \brief Returns true if the matcher matches the given \c DynNode.
+ bool matches(const ast_type_traits::DynTypedNode &DynNode,
+ ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const;
+
+ /// \brief Same as matches(), but skips the kind check.
+ ///
+ /// It is faster, but the caller must ensure the node is valid for the
+ /// kind of this matcher.
+ bool matchesNoKindCheck(const ast_type_traits::DynTypedNode &DynNode,
+ ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const;
+
+ /// \brief Bind the specified \p ID to the matcher.
+ /// \return A new matcher with the \p ID bound to it if this matcher supports
+ /// binding. Otherwise, returns an empty \c Optional<>.
+ llvm::Optional<DynTypedMatcher> tryBind(StringRef ID) const;
+
+ /// \brief Returns a unique \p ID for the matcher.
+ ///
+ /// Casting a Matcher<T> to Matcher<U> creates a matcher that has the
+ /// same \c Implementation pointer, but different \c RestrictKind. We need to
+ /// include both in the ID to make it unique.
+ ///
+ /// \c MatcherIDType supports operator< and provides strict weak ordering.
+ typedef std::pair<ast_type_traits::ASTNodeKind, uint64_t> MatcherIDType;
+ MatcherIDType getID() const {
+ /// FIXME: Document the requirements this imposes on matcher
+ /// implementations (no new() implementation_ during a Matches()).
+ return std::make_pair(RestrictKind,
+ reinterpret_cast<uint64_t>(Implementation.get()));
+ }
+
+ /// \brief Returns the type this matcher works on.
+ ///
+ /// \c matches() will always return false unless the node passed is of this
+ /// or a derived type.
+ ast_type_traits::ASTNodeKind getSupportedKind() const {
+ return SupportedKind;
+ }
+
+ /// \brief Returns \c true if the passed \c DynTypedMatcher can be converted
+ /// to a \c Matcher<T>.
+ ///
+ /// This method verifies that the underlying matcher in \c Other can process
+ /// nodes of types T.
+ template <typename T> bool canConvertTo() const {
+ return canConvertTo(ast_type_traits::ASTNodeKind::getFromNodeKind<T>());
+ }
+ bool canConvertTo(ast_type_traits::ASTNodeKind To) const;
+
+ /// \brief Construct a \c Matcher<T> interface around the dynamic matcher.
+ ///
+ /// This method asserts that \c canConvertTo() is \c true. Callers
+ /// should call \c canConvertTo() first to make sure that \c this is
+ /// compatible with T.
+ template <typename T> Matcher<T> convertTo() const {
+ assert(canConvertTo<T>());
+ return unconditionalConvertTo<T>();
+ }
+
+ /// \brief Same as \c convertTo(), but does not check that the underlying
+ /// matcher can handle a value of T.
+ ///
+ /// If it is not compatible, then this matcher will never match anything.
+ template <typename T> Matcher<T> unconditionalConvertTo() const;
+
+private:
+ DynTypedMatcher(ast_type_traits::ASTNodeKind SupportedKind,
+ ast_type_traits::ASTNodeKind RestrictKind,
+ IntrusiveRefCntPtr<DynMatcherInterface> Implementation)
+ : AllowBind(false),
+ SupportedKind(SupportedKind),
+ RestrictKind(RestrictKind),
+ Implementation(std::move(Implementation)) {}
+
+ bool AllowBind;
+ ast_type_traits::ASTNodeKind SupportedKind;
+ /// \brief A potentially stricter node kind.
+ ///
+ /// It allows to perform implicit and dynamic cast of matchers without
+ /// needing to change \c Implementation.
+ ast_type_traits::ASTNodeKind RestrictKind;
+ IntrusiveRefCntPtr<DynMatcherInterface> Implementation;
+};
+
/// \brief Wrapper of a MatcherInterface<T> *that allows copying.
///
/// A Matcher<Base> can be used anywhere a Matcher<Derived> is
@@ -221,7 +403,10 @@ public:
Matcher(const Matcher<From> &Other,
typename std::enable_if<std::is_base_of<From, T>::value &&
!std::is_same<From, T>::value>::type * = 0)
- : Implementation(new ImplicitCastMatcher<From>(Other)) {}
+ : Implementation(restrictMatcher(Other.Implementation)) {
+ assert(Implementation.getSupportedKind().isSame(
+ ast_type_traits::ASTNodeKind::getFromNodeKind<T>()));
+ }
/// \brief Implicitly converts \c Matcher<Type> to \c Matcher<QualType>.
///
@@ -233,26 +418,34 @@ public:
std::is_same<TypeT, Type>::value>::type* = 0)
: Implementation(new TypeToQualType<TypeT>(Other)) {}
+ /// \brief Convert \c this into a \c Matcher<T> by applying dyn_cast<> to the
+ /// argument.
+ /// \c To must be a base class of \c T.
+ template <typename To>
+ Matcher<To> dynCastTo() const {
+ static_assert(std::is_base_of<To, T>::value, "Invalid dynCast call.");
+ return Matcher<To>(Implementation);
+ }
+
/// \brief Forwards the call to the underlying MatcherInterface<T> pointer.
bool matches(const T &Node,
ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const {
- if (Implementation->matches(Node, Finder, Builder))
- return true;
- // Delete all bindings when a matcher does not match.
- // This prevents unexpected exposure of bound nodes in unmatches
- // branches of the match tree.
- *Builder = BoundNodesTreeBuilder();
- return false;
+ return Implementation.matches(ast_type_traits::DynTypedNode::create(Node),
+ Finder, Builder);
}
/// \brief Returns an ID that uniquely identifies the matcher.
- 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.get());
+ DynTypedMatcher::MatcherIDType getID() const {
+ return Implementation.getID();
}
+ /// \brief Extract the dynamic matcher.
+ ///
+ /// The returned matcher keeps the same restrictions as \c this and remembers
+ /// that it is meant to support nodes of type \c T.
+ operator DynTypedMatcher() const { return Implementation; }
+
/// \brief Allows the conversion of a \c Matcher<Type> to a \c
/// Matcher<QualType>.
///
@@ -276,24 +469,22 @@ public:
};
private:
- /// \brief Allows conversion from Matcher<Base> to Matcher<T> if T
- /// is derived from Base.
- template <typename Base>
- class ImplicitCastMatcher : public MatcherInterface<T> {
- public:
- explicit ImplicitCastMatcher(const Matcher<Base> &From)
- : From(From) {}
+ // For Matcher<T> <=> Matcher<U> conversions.
+ template <typename U> friend class Matcher;
+ // For DynTypedMatcher::unconditionalConvertTo<T>.
+ friend class DynTypedMatcher;
- bool matches(const T &Node, ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const override {
- return From.matches(Node, Finder, Builder);
- }
+ static DynTypedMatcher restrictMatcher(const DynTypedMatcher &Other) {
+ return Other.dynCastTo(ast_type_traits::ASTNodeKind::getFromNodeKind<T>());
+ }
- private:
- const Matcher<Base> From;
- };
+ explicit Matcher(const DynTypedMatcher &Implementation)
+ : Implementation(restrictMatcher(Implementation)) {
+ assert(this->Implementation.getSupportedKind()
+ .isSame(ast_type_traits::ASTNodeKind::getFromNodeKind<T>()));
+ }
- IntrusiveRefCntPtr< MatcherInterface<T> > Implementation;
+ DynTypedMatcher Implementation;
}; // class Matcher
/// \brief A convenient helper for creating a Matcher<T> without specifying
@@ -303,153 +494,10 @@ inline Matcher<T> makeMatcher(MatcherInterface<T> *Implementation) {
return Matcher<T>(Implementation);
}
-template <typename T> class BindableMatcher;
-
-/// \brief Matcher that works on a \c DynTypedNode.
-///
-/// It is constructed from a \c Matcher<T> object and redirects most calls to
-/// underlying matcher.
-/// It checks whether the \c DynTypedNode is convertible into the type of the
-/// underlying matcher and then do the actual match on the actual node, or
-/// return false if it is not convertible.
-class DynTypedMatcher {
-public:
- /// \brief Construct from a \c Matcher<T>. Copies the matcher.
- template <typename T> inline DynTypedMatcher(const Matcher<T> &M);
-
- /// \brief Construct from a bindable \c Matcher<T>. Copies the matcher.
- ///
- /// This version enables \c tryBind() on the \c DynTypedMatcher.
- template <typename T> inline DynTypedMatcher(const BindableMatcher<T> &M);
-
- /// \brief Returns true if the matcher matches the given \c DynNode.
- bool matches(const ast_type_traits::DynTypedNode DynNode,
- ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const {
- return Storage->matches(DynNode, Finder, Builder);
- }
-
- /// \brief Bind the specified \p ID to the matcher.
- /// \return A new matcher with the \p ID bound to it if this matcher supports
- /// binding. Otherwise, returns an empty \c Optional<>.
- llvm::Optional<DynTypedMatcher> tryBind(StringRef ID) const {
- return Storage->tryBind(ID);
- }
-
- /// \brief Returns a unique \p ID for the matcher.
- uint64_t getID() const { return Storage->getID(); }
-
- /// \brief Returns the type this matcher works on.
- ///
- /// \c matches() will always return false unless the node passed is of this
- /// or a derived type.
- ast_type_traits::ASTNodeKind getSupportedKind() const {
- return Storage->getSupportedKind();
- }
-
- /// \brief Returns \c true if the passed \c DynTypedMatcher can be converted
- /// to a \c Matcher<T>.
- ///
- /// This method verifies that the underlying matcher in \c Other can process
- /// nodes of types T.
- template <typename T> bool canConvertTo() const {
- return getSupportedKind().isBaseOf(
- ast_type_traits::ASTNodeKind::getFromNodeKind<T>());
- }
-
- /// \brief Construct a \c Matcher<T> interface around the dynamic matcher.
- ///
- /// This method asserts that \c canConvertTo() is \c true. Callers
- /// should call \c canConvertTo() first to make sure that \c this is
- /// compatible with T.
- template <typename T> Matcher<T> convertTo() const {
- assert(canConvertTo<T>());
- return unconditionalConvertTo<T>();
- }
-
- /// \brief Same as \c convertTo(), but does not check that the underlying
- /// matcher can handle a value of T.
- ///
- /// If it is not compatible, then this matcher will never match anything.
- template <typename T> Matcher<T> unconditionalConvertTo() const;
-
-private:
- class MatcherStorage : public RefCountedBaseVPTR {
- public:
- MatcherStorage(ast_type_traits::ASTNodeKind SupportedKind, uint64_t ID)
- : SupportedKind(SupportedKind), ID(ID) {}
- virtual ~MatcherStorage();
-
- virtual bool matches(const ast_type_traits::DynTypedNode DynNode,
- ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const = 0;
-
- virtual llvm::Optional<DynTypedMatcher> tryBind(StringRef ID) const = 0;
-
- ast_type_traits::ASTNodeKind getSupportedKind() const {
- return SupportedKind;
- }
-
- uint64_t getID() const { return ID; }
-
- private:
- const ast_type_traits::ASTNodeKind SupportedKind;
- const uint64_t ID;
- };
-
- /// \brief Typed implementation of \c MatcherStorage.
- template <typename T> class TypedMatcherStorage;
-
- IntrusiveRefCntPtr<const MatcherStorage> Storage;
-};
-
-template <typename T>
-class DynTypedMatcher::TypedMatcherStorage : public MatcherStorage {
-public:
- TypedMatcherStorage(const Matcher<T> &Other, bool AllowBind)
- : MatcherStorage(ast_type_traits::ASTNodeKind::getFromNodeKind<T>(),
- Other.getID()),
- InnerMatcher(Other), AllowBind(AllowBind) {}
-
- bool matches(const ast_type_traits::DynTypedNode DynNode,
- 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 override {
- if (!AllowBind)
- return llvm::Optional<DynTypedMatcher>();
- return DynTypedMatcher(BindableMatcher<T>(InnerMatcher).bind(ID));
- }
-
-private:
- const Matcher<T> InnerMatcher;
- const bool AllowBind;
-};
-
-template <typename T>
-inline DynTypedMatcher::DynTypedMatcher(const Matcher<T> &M)
- : Storage(new TypedMatcherStorage<T>(M, false)) {}
-
-template <typename T>
-inline DynTypedMatcher::DynTypedMatcher(const BindableMatcher<T> &M)
- : Storage(new TypedMatcherStorage<T>(M, true)) {}
-
/// \brief Specialization of the conversion functions for QualType.
///
-/// These specializations provide the Matcher<Type>->Matcher<QualType>
+/// This specialization provides the Matcher<Type>->Matcher<QualType>
/// conversion that the static API does.
-template <> inline bool DynTypedMatcher::canConvertTo<QualType>() const {
- const ast_type_traits::ASTNodeKind SourceKind = getSupportedKind();
- return SourceKind.isSame(
- ast_type_traits::ASTNodeKind::getFromNodeKind<Type>()) ||
- SourceKind.isSame(
- ast_type_traits::ASTNodeKind::getFromNodeKind<QualType>());
-}
-
template <>
inline Matcher<QualType> DynTypedMatcher::convertTo<QualType>() const {
assert(canConvertTo<QualType>());
@@ -470,7 +518,7 @@ bool matchesFirstInRange(const MatcherT &Matcher, IteratorT Start,
for (IteratorT I = Start; I != End; ++I) {
BoundNodesTreeBuilder Result(*Builder);
if (Matcher.matches(*I, Finder, &Result)) {
- *Builder = Result;
+ *Builder = std::move(Result);
return true;
}
}
@@ -486,7 +534,7 @@ bool matchesFirstInPointerRange(const MatcherT &Matcher, IteratorT Start,
for (IteratorT I = Start; I != End; ++I) {
BoundNodesTreeBuilder Result(*Builder);
if (Matcher.matches(**I, Finder, &Result)) {
- *Builder = Result;
+ *Builder = std::move(Result);
return true;
}
}
@@ -549,6 +597,33 @@ private:
std::string Name;
};
+/// \brief Matches named declarations with a specific name.
+///
+/// See \c hasName() in ASTMatchers.h for details.
+class HasNameMatcher : public SingleNodeMatcherInterface<NamedDecl> {
+ public:
+ explicit HasNameMatcher(StringRef Name);
+
+ bool matchesNode(const NamedDecl &Node) const override;
+
+ private:
+ /// \brief Unqualified match routine.
+ ///
+ /// It is much faster than the full match, but it only works for unqualified
+ /// matches.
+ bool matchesNodeUnqualified(const NamedDecl &Node) const;
+
+ /// \brief Full match routine
+ ///
+ /// It generates the fully qualified name of the declaration (which is
+ /// expensive) before trying to match.
+ /// It is slower but simple and works on all cases.
+ bool matchesNodeFull(const NamedDecl &Node) const;
+
+ const bool UseUnqualifiedMatch;
+ const std::string Name;
+};
+
/// \brief Matches declarations for QualType and CallExpr.
///
/// Type argument DeclMatcherT is required by PolymorphicMatcherWithParam1 but
@@ -973,46 +1048,16 @@ private:
///
/// This is useful when a matcher syntactically requires a child matcher,
/// but the context doesn't care. See for example: anything().
-///
-/// FIXME: Alternatively we could also create a IsAMatcher or something
-/// that checks that a dyn_cast is possible. This is purely needed for the
-/// difference between calling for example:
-/// record()
-/// and
-/// record(SomeMatcher)
-/// In the second case we need the correct type we were dyn_cast'ed to in order
-/// to get the right type for the inner matcher. In the first case we don't need
-/// that, but we use the type conversion anyway and insert a TrueMatcher.
-template <typename T>
-class TrueMatcher : public SingleNodeMatcherInterface<T> {
-public:
- bool matchesNode(const T &Node) const override {
- return true;
- }
-};
-
-/// \brief Matcher<T> that wraps an inner Matcher<T> and binds the matched node
-/// to an ID if the inner matcher matches on the node.
-template <typename T>
-class IdMatcher : public MatcherInterface<T> {
-public:
- /// \brief Creates an IdMatcher that binds to 'ID' if 'InnerMatcher' matches
- /// the node.
- IdMatcher(StringRef ID, const Matcher<T> &InnerMatcher)
- : ID(ID), InnerMatcher(InnerMatcher) {}
+class TrueMatcher {
+ public:
+ typedef AllNodeBaseTypes ReturnTypes;
- bool matches(const T &Node, ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const override {
- bool Result = InnerMatcher.matches(Node, Finder, Builder);
- if (Result) {
- Builder->setBinding(ID, &Node);
- }
- return Result;
+ template <typename T>
+ operator Matcher<T>() const {
+ return DynTypedMatcher::trueMatcher(
+ ast_type_traits::ASTNodeKind::getFromNodeKind<T>())
+ .template unconditionalConvertTo<T>();
}
-
-private:
- const std::string ID;
- const Matcher<T> InnerMatcher;
};
/// \brief A Matcher that allows binding the node it matches to an id.
@@ -1031,7 +1076,17 @@ public:
/// The returned matcher is equivalent to this matcher, but will
/// bind the matched node on a match.
Matcher<T> bind(StringRef ID) const {
- return Matcher<T>(new IdMatcher<T>(ID, *this));
+ return DynTypedMatcher(*this)
+ .tryBind(ID)
+ ->template unconditionalConvertTo<T>();
+ }
+
+ /// \brief Same as Matcher<T>'s conversion operator, but enables binding on
+ /// the returned matcher.
+ operator DynTypedMatcher() const {
+ DynTypedMatcher Result = static_cast<const Matcher<T>&>(*this);
+ Result.setAllowBind(true);
+ return Result;
}
};
@@ -1089,36 +1144,11 @@ private:
/// \brief VariadicOperatorMatcher related types.
/// @{
-/// \brief Function signature for any variadic operator. It takes the inner
-/// matchers as an array of DynTypedMatcher.
-typedef bool (*VariadicOperatorFunction)(
- const ast_type_traits::DynTypedNode DynNode, ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder, ArrayRef<DynTypedMatcher> InnerMatchers);
-
-/// \brief \c MatcherInterface<T> implementation for an variadic operator.
-template <typename T>
-class VariadicOperatorMatcherInterface : public MatcherInterface<T> {
-public:
- VariadicOperatorMatcherInterface(VariadicOperatorFunction Func,
- std::vector<DynTypedMatcher> InnerMatchers)
- : Func(Func), InnerMatchers(std::move(InnerMatchers)) {}
-
- 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;
- const std::vector<DynTypedMatcher> InnerMatchers;
-};
-
/// \brief "No argument" placeholder to use as template paratemers.
struct VariadicOperatorNoArg {};
-/// \brief Polymorphic matcher object that uses a \c VariadicOperatorFunction
-/// operator.
+/// \brief Polymorphic matcher object that uses a \c
+/// DynTypedMatcher::VariadicOperator operator.
///
/// Input matchers can have any type (including other polymorphic matcher
/// types), and the actual Matcher<T> is generated on demand with an implicit
@@ -1133,7 +1163,8 @@ template <typename P1, typename P2 = VariadicOperatorNoArg,
typename P9 = VariadicOperatorNoArg>
class VariadicOperatorMatcher {
public:
- VariadicOperatorMatcher(VariadicOperatorFunction Func, const P1 &Param1,
+ VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op,
+ const P1 &Param1,
const P2 &Param2 = VariadicOperatorNoArg(),
const P3 &Param3 = VariadicOperatorNoArg(),
const P4 &Param4 = VariadicOperatorNoArg(),
@@ -1142,7 +1173,7 @@ public:
const P7 &Param7 = VariadicOperatorNoArg(),
const P8 &Param8 = VariadicOperatorNoArg(),
const P9 &Param9 = VariadicOperatorNoArg())
- : Func(Func), Param1(Param1), Param2(Param2), Param3(Param3),
+ : Op(Op), Param1(Param1), Param2(Param2), Param3(Param3),
Param4(Param4), Param5(Param5), Param6(Param6), Param7(Param7),
Param8(Param8), Param9(Param9) {}
@@ -1157,8 +1188,8 @@ public:
addMatcher<T>(Param7, Matchers);
addMatcher<T>(Param8, Matchers);
addMatcher<T>(Param9, Matchers);
- return Matcher<T>(
- new VariadicOperatorMatcherInterface<T>(Func, std::move(Matchers)));
+ return DynTypedMatcher::constructVariadic(Op, std::move(Matchers))
+ .template unconditionalConvertTo<T>();
}
private:
@@ -1173,7 +1204,7 @@ private:
static void addMatcher(VariadicOperatorNoArg,
std::vector<DynTypedMatcher> &Matchers) {}
- const VariadicOperatorFunction Func;
+ const DynTypedMatcher::VariadicOperator Op;
const P1 Param1;
const P2 Param2;
const P3 Param3;
@@ -1191,7 +1222,7 @@ private:
/// It supports 1-9 argument overloaded operator(). More can be added if needed.
template <unsigned MinCount, unsigned MaxCount>
struct VariadicOperatorMatcherFunc {
- VariadicOperatorFunction Func;
+ DynTypedMatcher::VariadicOperator Op;
template <unsigned Count, typename T>
struct EnableIfValidArity
@@ -1200,30 +1231,29 @@ struct VariadicOperatorMatcherFunc {
template <typename M1>
typename EnableIfValidArity<1, VariadicOperatorMatcher<M1> >::type
operator()(const M1 &P1) const {
- return VariadicOperatorMatcher<M1>(Func, P1);
+ return VariadicOperatorMatcher<M1>(Op, P1);
}
template <typename M1, typename M2>
typename EnableIfValidArity<2, VariadicOperatorMatcher<M1, M2> >::type
operator()(const M1 &P1, const M2 &P2) const {
- return VariadicOperatorMatcher<M1, M2>(Func, P1, P2);
+ return VariadicOperatorMatcher<M1, M2>(Op, P1, P2);
}
template <typename M1, typename M2, typename M3>
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);
+ return VariadicOperatorMatcher<M1, M2, M3>(Op, P1, P2, P3);
}
template <typename M1, typename M2, typename M3, typename 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);
+ return VariadicOperatorMatcher<M1, M2, M3, M4>(Op, P1, P2, P3, P4);
}
template <typename M1, typename M2, typename M3, typename M4, typename 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);
+ return VariadicOperatorMatcher<M1, M2, M3, M4, M5>(Op, P1, P2, P3, P4, P5);
}
template <typename M1, typename M2, typename M3, typename M4, typename M5,
typename M6>
@@ -1232,7 +1262,7 @@ struct VariadicOperatorMatcherFunc {
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);
+ Op, P1, P2, P3, P4, P5, P6);
}
template <typename M1, typename M2, typename M3, typename M4, typename M5,
typename M6, typename M7>
@@ -1241,7 +1271,7 @@ struct VariadicOperatorMatcherFunc {
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);
+ Op, P1, P2, P3, P4, P5, P6, P7);
}
template <typename M1, typename M2, typename M3, typename M4, typename M5,
typename M6, typename M7, typename M8>
@@ -1250,7 +1280,7 @@ struct VariadicOperatorMatcherFunc {
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);
+ Op, 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>
@@ -1260,55 +1290,40 @@ struct VariadicOperatorMatcherFunc {
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);
+ Op, 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,
- BoundNodesTreeBuilder *Builder,
- ArrayRef<DynTypedMatcher> InnerMatchers);
-
-/// \brief Matches nodes for which at least one of the provided matchers
-/// matches, but doesn't stop at the first match.
-bool EachOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
- ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder,
- ArrayRef<DynTypedMatcher> InnerMatchers);
-
-/// \brief Matches nodes for which at least one of the provided matchers
-/// matches.
-bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
- ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder,
- ArrayRef<DynTypedMatcher> InnerMatchers);
-
template <typename T>
inline Matcher<T> DynTypedMatcher::unconditionalConvertTo() const {
- return Matcher<T>(new VariadicOperatorMatcherInterface<T>(
- AllOfVariadicOperator, llvm::makeArrayRef(*this)));
+ return Matcher<T>(*this);
}
/// \brief Creates a Matcher<T> that matches if all inner matchers match.
template<typename T>
BindableMatcher<T> makeAllOfComposite(
ArrayRef<const Matcher<T> *> InnerMatchers) {
- std::vector<DynTypedMatcher> DynMatchers;
- for (size_t i = 0, e = InnerMatchers.size(); i != e; ++i) {
- DynMatchers.push_back(*InnerMatchers[i]);
+ // For the size() == 0 case, we return a "true" matcher.
+ if (InnerMatchers.size() == 0) {
+ return BindableMatcher<T>(TrueMatcher());
+ }
+ // For the size() == 1 case, we simply return that one matcher.
+ // No need to wrap it in a variadic operation.
+ if (InnerMatchers.size() == 1) {
+ return BindableMatcher<T>(*InnerMatchers[0]);
}
- return BindableMatcher<T>(new VariadicOperatorMatcherInterface<T>(
- AllOfVariadicOperator, std::move(DynMatchers)));
+
+ std::vector<DynTypedMatcher> DynMatchers;
+ DynMatchers.reserve(InnerMatchers.size());
+ for (const auto *InnerMatcher : InnerMatchers) {
+ DynMatchers.push_back(*InnerMatcher);
+ }
+ return BindableMatcher<T>(
+ DynTypedMatcher::constructVariadic(DynTypedMatcher::VO_AllOf,
+ std::move(DynMatchers))
+ .template unconditionalConvertTo<T>());
}
/// \brief Creates a Matcher<T> that matches if
@@ -1320,8 +1335,8 @@ BindableMatcher<T> makeAllOfComposite(
template<typename T, typename InnerT>
BindableMatcher<T> makeDynCastAllOfComposite(
ArrayRef<const Matcher<InnerT> *> InnerMatchers) {
- return BindableMatcher<T>(DynTypedMatcher(makeAllOfComposite(InnerMatchers))
- .unconditionalConvertTo<T>());
+ return BindableMatcher<T>(
+ makeAllOfComposite(InnerMatchers).template dynCastTo<T>());
}
/// \brief Matches nodes of type T that have at least one descendant node of
@@ -1606,6 +1621,23 @@ private:
const Matcher<InnerTBase> InnerMatcher;
};
+/// \brief A simple memoizer of T(*)() functions.
+///
+/// It will call the passed 'Func' template parameter at most once.
+/// Used to support AST_MATCHER_FUNCTION() macro.
+template <typename Matcher, Matcher (*Func)()> class MemoizedMatcher {
+ struct Wrapper {
+ Wrapper() : M(Func()) {}
+ Matcher M;
+ };
+
+public:
+ static const Matcher &getInstance() {
+ static llvm::ManagedStatic<Wrapper> Instance;
+ return Instance->M;
+ }
+};
+
// Define the create() method out of line to silence a GCC warning about
// the struct "Func" having greater visibility than its base, which comes from
// using the flag -fvisibility-inlines-hidden.
@@ -1627,7 +1659,7 @@ getTemplateSpecializationArgs(const ClassTemplateSpecializationDecl &D) {
inline ArrayRef<TemplateArgument>
getTemplateSpecializationArgs(const TemplateSpecializationType &T) {
- return ArrayRef<TemplateArgument>(T.getArgs(), T.getNumArgs());
+ return llvm::makeArrayRef(T.getArgs(), T.getNumArgs());
}
struct NotEqualsBoundNodePredicate {
@@ -1642,4 +1674,4 @@ struct NotEqualsBoundNodePredicate {
} // end namespace ast_matchers
} // end namespace clang
-#endif // LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_INTERNAL_H
+#endif
diff --git a/include/clang/ASTMatchers/ASTMatchersMacros.h b/include/clang/ASTMatchers/ASTMatchersMacros.h
index 563372a50609..b7888be7c176 100644
--- a/include/clang/ASTMatchers/ASTMatchersMacros.h
+++ b/include/clang/ASTMatchers/ASTMatchersMacros.h
@@ -34,8 +34,19 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H
-#define LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H
+#ifndef LLVM_CLANG_ASTMATCHERS_ASTMATCHERSMACROS_H
+#define LLVM_CLANG_ASTMATCHERS_ASTMATCHERSMACROS_H
+
+/// \brief AST_MATCHER_FUNCTION(ReturnType, DefineMatcher) {
+/// defines a zero parameter function named DefineMatcher() that returns a
+/// ReturnType object.
+#define AST_MATCHER_FUNCTION(ReturnType, DefineMatcher) \
+ inline ReturnType DefineMatcher##_getInstance(); \
+ inline ReturnType DefineMatcher() { \
+ return internal::MemoizedMatcher< \
+ ReturnType, DefineMatcher##_getInstance>::getInstance(); \
+ } \
+ inline ReturnType DefineMatcher##_getInstance()
/// \brief AST_MATCHER_FUNCTION_P(ReturnType, DefineMatcher, ParamType, Param) {
/// defines a single-parameter function named DefineMatcher() that returns a
@@ -352,4 +363,4 @@
internal::TypeLocTraverseMatcher, ReturnTypesF>::Func MatcherName##Loc; \
AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName##Type, ReturnTypesF)
-#endif // LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H
+#endif
diff --git a/include/clang/ASTMatchers/Dynamic/Diagnostics.h b/include/clang/ASTMatchers/Dynamic/Diagnostics.h
index 82a14f1929be..ef93ac54508d 100644
--- a/include/clang/ASTMatchers/Dynamic/Diagnostics.h
+++ b/include/clang/ASTMatchers/Dynamic/Diagnostics.h
@@ -12,8 +12,8 @@
///
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_DIAGNOSTICS_H
-#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_DIAGNOSTICS_H
+#ifndef LLVM_CLANG_ASTMATCHERS_DYNAMIC_DIAGNOSTICS_H
+#define LLVM_CLANG_ASTMATCHERS_DYNAMIC_DIAGNOSTICS_H
#include "clang/ASTMatchers/Dynamic/VariantValue.h"
#include "clang/Basic/LLVM.h"
diff --git a/include/clang/ASTMatchers/Dynamic/Parser.h b/include/clang/ASTMatchers/Dynamic/Parser.h
index 4045f57d1b36..bd006b6e1290 100644
--- a/include/clang/ASTMatchers/Dynamic/Parser.h
+++ b/include/clang/ASTMatchers/Dynamic/Parser.h
@@ -31,8 +31,8 @@
///
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_PARSER_H
-#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_PARSER_H
+#ifndef LLVM_CLANG_ASTMATCHERS_DYNAMIC_PARSER_H
+#define LLVM_CLANG_ASTMATCHERS_DYNAMIC_PARSER_H
#include "clang/ASTMatchers/Dynamic/Diagnostics.h"
#include "clang/ASTMatchers/Dynamic/Registry.h"
@@ -63,17 +63,6 @@ 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.
@@ -105,6 +94,29 @@ public:
/// found.
virtual llvm::Optional<MatcherCtor>
lookupMatcherCtor(StringRef MatcherName) = 0;
+
+ /// \brief Compute the list of completion types for \p Context.
+ ///
+ /// Each element of \p Context represents a matcher invocation, going from
+ /// outermost to innermost. Elements are pairs consisting of a reference to
+ /// the matcher constructor and the index of the next element in the
+ /// argument list of that matcher (or for the last element, the index of
+ /// the completion point in the argument list). An empty list requests
+ /// completion for the root matcher.
+ virtual std::vector<ArgKind> getAcceptedCompletionTypes(
+ llvm::ArrayRef<std::pair<MatcherCtor, unsigned>> Context);
+
+ /// \brief Compute the list of completions that match any of
+ /// \p AcceptedTypes.
+ ///
+ /// \param AcceptedTypes All types accepted for this completion.
+ ///
+ /// \return All completions for the specified types.
+ /// Completions should be valid when used in \c lookupMatcherCtor().
+ /// The matcher constructed from the return of \c lookupMatcherCtor()
+ /// should be convertible to some type in \p AcceptedTypes.
+ virtual std::vector<MatcherCompletion>
+ getMatcherCompletions(llvm::ArrayRef<ArgKind> AcceptedTypes);
};
/// \brief Sema implementation that uses the matcher registry to process the
@@ -121,58 +133,91 @@ public:
StringRef BindID,
ArrayRef<ParserValue> Args,
Diagnostics *Error) override;
+
+ std::vector<ArgKind> getAcceptedCompletionTypes(
+ llvm::ArrayRef<std::pair<MatcherCtor, unsigned>> Context) override;
+
+ std::vector<MatcherCompletion>
+ getMatcherCompletions(llvm::ArrayRef<ArgKind> AcceptedTypes) override;
};
- /// \brief Parse a matcher expression, creating matchers from the registry.
- ///
- /// This overload creates matchers calling directly into the registry. If the
- /// caller needs more control over how the matchers are created, then it can
- /// use the overload below that takes a Sema.
- ///
- /// \param MatcherCode The matcher expression to parse.
- ///
- /// \return The matcher object constructed, or an empty Optional if an error
- /// occurred.
- /// In that case, \c Error will contain a description of the error.
- /// The caller takes ownership of the DynTypedMatcher object returned.
- static llvm::Optional<DynTypedMatcher>
- parseMatcherExpression(StringRef MatcherCode, Diagnostics *Error);
+ typedef llvm::StringMap<VariantValue> NamedValueMap;
/// \brief Parse a matcher expression.
///
/// \param MatcherCode The matcher expression to parse.
///
/// \param S The Sema instance that will help the parser
- /// construct the matchers.
+ /// construct the matchers. If null, it uses the default registry.
+ ///
+ /// \param NamedValues A map of precomputed named values. This provides
+ /// the dictionary for the <NamedValue> rule of the grammar.
+ /// If null, it is ignored.
+ ///
/// \return The matcher object constructed by the processor, or an empty
/// Optional if an error occurred. In that case, \c Error will contain a
/// description of the error.
/// The caller takes ownership of the DynTypedMatcher object returned.
static llvm::Optional<DynTypedMatcher>
- parseMatcherExpression(StringRef MatcherCode, Sema *S, Diagnostics *Error);
-
- /// \brief Parse an expression, creating matchers from the registry.
- ///
- /// Parses any expression supported by this parser. In general, the
- /// \c parseMatcherExpression function is a better approach to get a matcher
- /// object.
- static bool parseExpression(StringRef Code, VariantValue *Value,
- Diagnostics *Error);
+ parseMatcherExpression(StringRef MatcherCode, Sema *S,
+ const NamedValueMap *NamedValues,
+ Diagnostics *Error);
+ static llvm::Optional<DynTypedMatcher>
+ parseMatcherExpression(StringRef MatcherCode, Sema *S,
+ Diagnostics *Error) {
+ return parseMatcherExpression(MatcherCode, S, nullptr, Error);
+ }
+ static llvm::Optional<DynTypedMatcher>
+ parseMatcherExpression(StringRef MatcherCode, Diagnostics *Error) {
+ return parseMatcherExpression(MatcherCode, nullptr, Error);
+ }
/// \brief Parse an expression.
///
/// Parses any expression supported by this parser. In general, the
/// \c parseMatcherExpression function is a better approach to get a matcher
/// object.
+ ///
+ /// \param S The Sema instance that will help the parser
+ /// construct the matchers. If null, it uses the default registry.
+ ///
+ /// \param NamedValues A map of precomputed named values. This provides
+ /// the dictionary for the <NamedValue> rule of the grammar.
+ /// If null, it is ignored.
static bool parseExpression(StringRef Code, Sema *S,
+ const NamedValueMap *NamedValues,
VariantValue *Value, Diagnostics *Error);
+ static bool parseExpression(StringRef Code, Sema *S,
+ VariantValue *Value, Diagnostics *Error) {
+ return parseExpression(Code, S, nullptr, Value, Error);
+ }
+ static bool parseExpression(StringRef Code, VariantValue *Value,
+ Diagnostics *Error) {
+ return parseExpression(Code, nullptr, Value, Error);
+ }
/// \brief Complete an expression at the given offset.
///
+ /// \param S The Sema instance that will help the parser
+ /// construct the matchers. If null, it uses the default registry.
+ ///
+ /// \param NamedValues A map of precomputed named values. This provides
+ /// the dictionary for the <NamedValue> rule of the grammar.
+ /// If null, it is ignored.
+ ///
/// \return The list of completions, which may be empty if there are no
/// available completions or if an error occurred.
static std::vector<MatcherCompletion>
- completeExpression(StringRef Code, unsigned CompletionOffset);
+ completeExpression(StringRef Code, unsigned CompletionOffset, Sema *S,
+ const NamedValueMap *NamedValues);
+ static std::vector<MatcherCompletion>
+ completeExpression(StringRef Code, unsigned CompletionOffset, Sema *S) {
+ return completeExpression(Code, CompletionOffset, S, nullptr);
+ }
+ static std::vector<MatcherCompletion>
+ completeExpression(StringRef Code, unsigned CompletionOffset) {
+ return completeExpression(Code, CompletionOffset, nullptr);
+ }
private:
class CodeTokenizer;
@@ -180,6 +225,7 @@ private:
struct TokenInfo;
Parser(CodeTokenizer *Tokenizer, Sema *S,
+ const NamedValueMap *NamedValues,
Diagnostics *Error);
bool parseExpressionImpl(VariantValue *Value);
@@ -187,12 +233,16 @@ private:
VariantValue *Value);
bool parseIdentifierPrefixImpl(VariantValue *Value);
- void addCompletion(const TokenInfo &CompToken, StringRef TypedText,
- StringRef Decl);
+ void addCompletion(const TokenInfo &CompToken,
+ const MatcherCompletion &Completion);
void addExpressionCompletions();
+ std::vector<MatcherCompletion>
+ getNamedValueCompletions(ArrayRef<ArgKind> AcceptedTypes);
+
CodeTokenizer *const Tokenizer;
Sema *const S;
+ const NamedValueMap *const NamedValues;
Diagnostics *const Error;
typedef std::vector<std::pair<MatcherCtor, unsigned> > ContextStackTy;
diff --git a/include/clang/ASTMatchers/Dynamic/Registry.h b/include/clang/ASTMatchers/Dynamic/Registry.h
index faa9254bc2e7..ad24a8d1b794 100644
--- a/include/clang/ASTMatchers/Dynamic/Registry.h
+++ b/include/clang/ASTMatchers/Dynamic/Registry.h
@@ -14,8 +14,8 @@
///
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_REGISTRY_H
-#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_REGISTRY_H
+#ifndef LLVM_CLANG_ASTMATCHERS_DYNAMIC_REGISTRY_H
+#define LLVM_CLANG_ASTMATCHERS_DYNAMIC_REGISTRY_H
#include "clang/ASTMatchers/Dynamic/Diagnostics.h"
#include "clang/ASTMatchers/Dynamic/VariantValue.h"
@@ -36,8 +36,10 @@ typedef const internal::MatcherDescriptor *MatcherCtor;
struct MatcherCompletion {
MatcherCompletion() {}
- MatcherCompletion(StringRef TypedText, StringRef MatcherDecl)
- : TypedText(TypedText), MatcherDecl(MatcherDecl) {}
+ MatcherCompletion(StringRef TypedText, StringRef MatcherDecl,
+ unsigned Specificity)
+ : TypedText(TypedText), MatcherDecl(MatcherDecl),
+ Specificity(Specificity) {}
/// \brief The text to type to select this matcher.
std::string TypedText;
@@ -45,6 +47,13 @@ struct MatcherCompletion {
/// \brief The "declaration" of the matcher, with type information.
std::string MatcherDecl;
+ /// \brief Value corresponding to the "specificity" of the converted matcher.
+ ///
+ /// Zero specificity indicates that this conversion would produce a trivial
+ /// matcher that will either always or never match.
+ /// Such matchers are excluded from code completion results.
+ unsigned Specificity;
+
bool operator==(const MatcherCompletion &Other) const {
return TypedText == Other.TypedText && MatcherDecl == Other.MatcherDecl;
}
@@ -58,28 +67,28 @@ public:
/// constructor, or Optional<MatcherCtor>() if not found.
static llvm::Optional<MatcherCtor> lookupMatcherCtor(StringRef MatcherName);
- /// \brief Compute the list of completions for \p Context.
+ /// \brief Compute the list of completion types for \p Context.
///
/// Each element of \p Context represents a matcher invocation, going from
- /// outermost to innermost. Elements are pairs consisting of a reference to the
- /// matcher constructor and the index of the next element in the argument list
- /// of that matcher (or for the last element, the index of the completion
- /// point in the argument list). An empty list requests completion for the
- /// root matcher.
+ /// outermost to innermost. Elements are pairs consisting of a reference to
+ /// the matcher constructor and the index of the next element in the
+ /// argument list of that matcher (or for the last element, the index of
+ /// the completion point in the argument list). An empty list requests
+ /// completion for the root matcher.
+ static std::vector<ArgKind> getAcceptedCompletionTypes(
+ llvm::ArrayRef<std::pair<MatcherCtor, unsigned>> Context);
+
+ /// \brief Compute the list of completions that match any of
+ /// \p AcceptedTypes.
///
- /// 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.
+ /// \param AcceptedTypes All types accepted for this completion.
///
- /// 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.
+ /// \return All completions for the specified types.
+ /// Completions should be valid when used in \c lookupMatcherCtor().
+ /// The matcher constructed from the return of \c lookupMatcherCtor()
+ /// should be convertible to some type in \p AcceptedTypes.
static std::vector<MatcherCompletion>
- getCompletions(ArrayRef<std::pair<MatcherCtor, unsigned> > Context);
+ getMatcherCompletions(ArrayRef<ArgKind> AcceptedTypes);
/// \brief Construct a matcher from the registry.
///
diff --git a/include/clang/ASTMatchers/Dynamic/VariantValue.h b/include/clang/ASTMatchers/Dynamic/VariantValue.h
index b25267b1c54b..a9bd3d50115a 100644
--- a/include/clang/ASTMatchers/Dynamic/VariantValue.h
+++ b/include/clang/ASTMatchers/Dynamic/VariantValue.h
@@ -14,8 +14,8 @@
///
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H
-#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H
+#ifndef LLVM_CLANG_ASTMATCHERS_DYNAMIC_VARIANTVALUE_H
+#define LLVM_CLANG_ASTMATCHERS_DYNAMIC_VARIANTVALUE_H
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/ASTMatchers/ASTMatchersInternal.h"
@@ -29,6 +29,51 @@ namespace clang {
namespace ast_matchers {
namespace dynamic {
+/// \brief Kind identifier.
+///
+/// It supports all types that VariantValue can contain.
+class ArgKind {
+ public:
+ enum Kind {
+ AK_Matcher,
+ AK_Unsigned,
+ AK_String
+ };
+ /// \brief Constructor for non-matcher types.
+ ArgKind(Kind K) : K(K) { assert(K != AK_Matcher); }
+
+ /// \brief Constructor for matcher types.
+ ArgKind(ast_type_traits::ASTNodeKind MatcherKind)
+ : K(AK_Matcher), MatcherKind(MatcherKind) {}
+
+ Kind getArgKind() const { return K; }
+ ast_type_traits::ASTNodeKind getMatcherKind() const {
+ assert(K == AK_Matcher);
+ return MatcherKind;
+ }
+
+ /// \brief Determines if this type can be converted to \p To.
+ ///
+ /// \param To the requested destination type.
+ ///
+ /// \param Specificity value corresponding to the "specificity" of the
+ /// convertion.
+ bool isConvertibleTo(ArgKind To, unsigned *Specificity) const;
+
+ bool operator<(const ArgKind &Other) const {
+ if (K == AK_Matcher && Other.K == AK_Matcher)
+ return MatcherKind < Other.MatcherKind;
+ return K < Other.K;
+ }
+
+ /// \brief String representation of the type.
+ std::string asString() const;
+
+private:
+ Kind K;
+ ast_type_traits::ASTNodeKind MatcherKind;
+};
+
using ast_matchers::internal::DynTypedMatcher;
/// \brief A variant matcher object.
@@ -48,13 +93,28 @@ class VariantMatcher {
/// \brief Methods that depend on T from hasTypedMatcher/getTypedMatcher.
class MatcherOps {
public:
- virtual ~MatcherOps();
- 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,
- ArrayRef<VariantMatcher> InnerMatchers) = 0;
+ MatcherOps(ast_type_traits::ASTNodeKind NodeKind) : NodeKind(NodeKind) {}
+
+ bool canConstructFrom(const DynTypedMatcher &Matcher,
+ bool &IsExactMatch) const;
+
+ /// \brief Convert \p Matcher the destination type and return it as a new
+ /// DynTypedMatcher.
+ virtual DynTypedMatcher
+ convertMatcher(const DynTypedMatcher &Matcher) const = 0;
+
+ /// \brief Constructs a variadic typed matcher from \p InnerMatchers.
+ /// Will try to convert each inner matcher to the destination type and
+ /// return llvm::None if it fails to do so.
+ llvm::Optional<DynTypedMatcher>
+ constructVariadicOperator(DynTypedMatcher::VariadicOperator Op,
+ ArrayRef<VariantMatcher> InnerMatchers) const;
+
+ protected:
+ ~MatcherOps() {}
+
+ private:
+ ast_type_traits::ASTNodeKind NodeKind;
};
/// \brief Payload interface to be specialized by each matcher type.
@@ -65,7 +125,10 @@ class VariantMatcher {
virtual ~Payload();
virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const = 0;
virtual std::string getTypeAsString() const = 0;
- virtual void makeTypedMatcher(MatcherOps &Ops) const = 0;
+ virtual llvm::Optional<DynTypedMatcher>
+ getTypedMatcher(const MatcherOps &Ops) const = 0;
+ virtual bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
+ unsigned *Specificity) const = 0;
};
public:
@@ -84,9 +147,9 @@ public:
/// \brief Creates a 'variadic' operator matcher.
///
/// It will bind to the appropriate type on getTypedMatcher<T>().
- static VariantMatcher VariadicOperatorMatcher(
- ast_matchers::internal::VariadicOperatorFunction Func,
- std::vector<VariantMatcher> Args);
+ static VariantMatcher
+ VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op,
+ std::vector<VariantMatcher> Args);
/// \brief Makes the matcher the "null" matcher.
void reset();
@@ -111,9 +174,21 @@ public:
/// that can, the result would be ambiguous and false is returned.
template <class T>
bool hasTypedMatcher() const {
- TypedMatcherOps<T> Ops;
- if (Value) Value->makeTypedMatcher(Ops);
- return Ops.hasMatcher();
+ if (!Value) return false;
+ return Value->getTypedMatcher(TypedMatcherOps<T>()).hasValue();
+ }
+
+ /// \brief Determines if the contained matcher can be converted to \p Kind.
+ ///
+ /// \param Kind the requested destination type.
+ ///
+ /// \param Specificity value corresponding to the "specificity" of the
+ /// convertion.
+ bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
+ unsigned *Specificity) const {
+ if (Value)
+ return Value->isConvertibleTo(Kind, Specificity);
+ return false;
}
/// \brief Return this matcher as a \c Matcher<T>.
@@ -122,10 +197,9 @@ public:
/// Asserts that \c hasTypedMatcher<T>() is true.
template <class T>
ast_matchers::internal::Matcher<T> getTypedMatcher() const {
- TypedMatcherOps<T> Ops;
- Value->makeTypedMatcher(Ops);
- assert(Ops.hasMatcher() && "hasTypedMatcher<T>() == false");
- return Ops.matcher();
+ assert(hasTypedMatcher<T>() && "hasTypedMatcher<T>() == false");
+ return Value->getTypedMatcher(TypedMatcherOps<T>())
+ ->template convertTo<T>();
}
/// \brief String representation of the type of the value.
@@ -137,51 +211,25 @@ public:
private:
explicit VariantMatcher(Payload *Value) : Value(Value) {}
+ template <typename T> struct TypedMatcherOps;
+
class SinglePayload;
class PolymorphicPayload;
class VariadicOpPayload;
- template <typename T>
- class TypedMatcherOps : public MatcherOps {
- public:
- typedef ast_matchers::internal::Matcher<T> MatcherT;
-
- virtual bool canConstructFrom(const DynTypedMatcher &Matcher,
- bool &IsExactMatch) const {
- IsExactMatch = Matcher.getSupportedKind().isSame(
- ast_type_traits::ASTNodeKind::getFromNodeKind<T>());
- return Matcher.canConvertTo<T>();
- }
-
- virtual void constructFrom(const DynTypedMatcher& Matcher) {
- Out.reset(new MatcherT(Matcher.convertTo<T>()));
- }
-
- virtual void constructVariadicOperator(
- ast_matchers::internal::VariadicOperatorFunction Func,
- ArrayRef<VariantMatcher> InnerMatchers) {
- 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>()) {
- return;
- }
- DynMatchers.push_back(InnerMatchers[i].getTypedMatcher<T>());
- }
- Out.reset(new MatcherT(
- new ast_matchers::internal::VariadicOperatorMatcherInterface<T>(
- Func, DynMatchers)));
- }
-
- bool hasMatcher() const { return Out.get() != nullptr; }
- const MatcherT &matcher() const { return *Out; }
+ IntrusiveRefCntPtr<const Payload> Value;
+};
- private:
- std::unique_ptr<MatcherT> Out;
- };
+template <typename T>
+struct VariantMatcher::TypedMatcherOps final : VariantMatcher::MatcherOps {
+ TypedMatcherOps()
+ : MatcherOps(ast_type_traits::ASTNodeKind::getFromNodeKind<T>()) {}
+ typedef ast_matchers::internal::Matcher<T> MatcherT;
- IntrusiveRefCntPtr<const Payload> Value;
+ DynTypedMatcher
+ convertMatcher(const DynTypedMatcher &Matcher) const override {
+ return DynTypedMatcher(Matcher.convertTo<T>());
+ }
};
/// \brief Variant value class.
@@ -228,6 +276,24 @@ public:
const VariantMatcher &getMatcher() const;
void setMatcher(const VariantMatcher &Matcher);
+ /// \brief Determines if the contained value can be converted to \p Kind.
+ ///
+ /// \param Kind the requested destination type.
+ ///
+ /// \param Specificity value corresponding to the "specificity" of the
+ /// convertion.
+ bool isConvertibleTo(ArgKind Kind, unsigned* Specificity) const;
+
+ /// \brief Determines if the contained value can be converted to any kind
+ /// in \p Kinds.
+ ///
+ /// \param Kinds the requested destination types.
+ ///
+ /// \param Specificity value corresponding to the "specificity" of the
+ /// convertion. It is the maximum specificity of all the possible
+ /// conversions.
+ bool isConvertibleTo(ArrayRef<ArgKind> Kinds, unsigned *Specificity) const;
+
/// \brief String representation of the type of the value.
std::string getTypeAsString() const;
diff --git a/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h b/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h
index a61d9e47881d..cc14c7bd33db 100644
--- a/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h
+++ b/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h
@@ -13,8 +13,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef CLANG_ANALYSIS_CFG_REACHABILITY
-#define CLANG_ANALYSIS_CFG_REACHABILITY
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_CFGREACHABILITYANALYSIS_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_CFGREACHABILITYANALYSIS_H
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/DenseMap.h"
diff --git a/include/clang/Analysis/Analyses/Consumed.h b/include/clang/Analysis/Analyses/Consumed.h
index 36e07c21907b..a7109233987c 100644
--- a/include/clang/Analysis/Analyses/Consumed.h
+++ b/include/clang/Analysis/Analyses/Consumed.h
@@ -12,8 +12,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_CONSUMED_H
-#define LLVM_CLANG_CONSUMED_H
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_CONSUMED_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_CONSUMED_H
#include "clang/AST/DeclCXX.h"
#include "clang/AST/ExprCXX.h"
diff --git a/include/clang/Analysis/Analyses/Dominators.h b/include/clang/Analysis/Analyses/Dominators.h
index 6c6d9238e5a9..fcef0fc10ac8 100644
--- a/include/clang/Analysis/Analyses/Dominators.h
+++ b/include/clang/Analysis/Analyses/Dominators.h
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_DOMINATORS_H
-#define LLVM_CLANG_DOMINATORS_H
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_DOMINATORS_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_DOMINATORS_H
#include "clang/Analysis/AnalysisContext.h"
#include "clang/Analysis/CFG.h"
diff --git a/include/clang/Analysis/Analyses/FormatString.h b/include/clang/Analysis/Analyses/FormatString.h
index 76fe9ddca6f8..174cce4f363c 100644
--- a/include/clang/Analysis/Analyses/FormatString.h
+++ b/include/clang/Analysis/Analyses/FormatString.h
@@ -16,8 +16,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_FORMAT_H
-#define LLVM_CLANG_FORMAT_H
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_FORMATSTRING_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_FORMATSTRING_H
#include "clang/AST/CanonicalType.h"
@@ -79,6 +79,7 @@ public:
AsLongDouble, // 'L'
AsAllocate, // for '%as', GNU extension to C90 scanf
AsMAllocate, // for '%ms', GNU extension to scanf
+ AsWide, // 'w' (MSVCRT, like l but only for c, C, s, S, or Z
AsWideChar = AsLong // for '%ls', only makes sense for printf
};
@@ -154,6 +155,8 @@ public:
// ** Printf-specific **
+ ZArg, // MS extension
+
// Objective-C specific specifiers.
ObjCObjArg, // '@'
ObjCBeg = ObjCObjArg, ObjCEnd = ObjCObjArg,
@@ -644,6 +647,9 @@ public:
bool ParsePrintfString(FormatStringHandler &H,
const char *beg, const char *end, const LangOptions &LO,
const TargetInfo &Target);
+
+bool ParseFormatStringHasSArg(const char *beg, const char *end, const LangOptions &LO,
+ const TargetInfo &Target);
bool ParseScanfString(FormatStringHandler &H,
const char *beg, const char *end, const LangOptions &LO,
diff --git a/include/clang/Analysis/Analyses/LiveVariables.h b/include/clang/Analysis/Analyses/LiveVariables.h
index 784227108ead..c29dd409e56c 100644
--- a/include/clang/Analysis/Analyses/LiveVariables.h
+++ b/include/clang/Analysis/Analyses/LiveVariables.h
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_LIVEVARIABLES_H
-#define LLVM_CLANG_LIVEVARIABLES_H
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_LIVEVARIABLES_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_LIVEVARIABLES_H
#include "clang/AST/Decl.h"
#include "clang/Analysis/AnalysisContext.h"
diff --git a/include/clang/Analysis/Analyses/PostOrderCFGView.h b/include/clang/Analysis/Analyses/PostOrderCFGView.h
index 91bf51cd613f..a1c650427588 100644
--- a/include/clang/Analysis/Analyses/PostOrderCFGView.h
+++ b/include/clang/Analysis/Analyses/PostOrderCFGView.h
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_POSTORDER_CFGVIEW
-#define LLVM_CLANG_POSTORDER_CFGVIEW
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_POSTORDERCFGVIEW_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_POSTORDERCFGVIEW_H
#include <vector>
//#include <algorithm>
@@ -47,17 +47,17 @@ public:
/// \brief Set the bit associated with a particular CFGBlock.
/// This is the important method for the SetType template parameter.
- bool insert(const CFGBlock *Block) {
+ std::pair<llvm::NoneType, bool> insert(const CFGBlock *Block) {
// Note that insert() is called by po_iterator, which doesn't check to
// make sure that Block is non-null. Moreover, the CFGBlock iterator will
// occasionally hand out null pointers for pruned edges, so we catch those
// here.
if (!Block)
- return false; // if an edge is trivially false.
+ return std::make_pair(None, false); // if an edge is trivially false.
if (VisitedBlockIDs.test(Block->getBlockID()))
- return false;
+ return std::make_pair(None, false);
VisitedBlockIDs.set(Block->getBlockID());
- return true;
+ return std::make_pair(None, true);
}
/// \brief Check if the bit for a CFGBlock has been already set.
diff --git a/include/clang/Analysis/Analyses/PseudoConstantAnalysis.h b/include/clang/Analysis/Analyses/PseudoConstantAnalysis.h
index cb73850b08c7..c4ec2f22eca0 100644
--- a/include/clang/Analysis/Analyses/PseudoConstantAnalysis.h
+++ b/include/clang/Analysis/Analyses/PseudoConstantAnalysis.h
@@ -13,8 +13,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_ANALYSIS_PSEUDOCONSTANTANALYSIS
-#define LLVM_CLANG_ANALYSIS_PSEUDOCONSTANTANALYSIS
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_PSEUDOCONSTANTANALYSIS_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_PSEUDOCONSTANTANALYSIS_H
#include "clang/AST/Stmt.h"
diff --git a/include/clang/Analysis/Analyses/ReachableCode.h b/include/clang/Analysis/Analyses/ReachableCode.h
index 90a6d014f58d..4c523bfc8b56 100644
--- a/include/clang/Analysis/Analyses/ReachableCode.h
+++ b/include/clang/Analysis/Analyses/ReachableCode.h
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_REACHABLECODE_H
-#define LLVM_CLANG_REACHABLECODE_H
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_REACHABLECODE_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_REACHABLECODE_H
#include "clang/Basic/SourceLocation.h"
diff --git a/include/clang/Analysis/Analyses/ThreadSafety.h b/include/clang/Analysis/Analyses/ThreadSafety.h
index b533c1db492e..458bb576f459 100644
--- a/include/clang/Analysis/Analyses/ThreadSafety.h
+++ b/include/clang/Analysis/Analyses/ThreadSafety.h
@@ -16,31 +16,33 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_THREADSAFETY_H
-#define LLVM_CLANG_THREADSAFETY_H
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETY_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETY_H
#include "clang/Analysis/AnalysisContext.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/StringRef.h"
namespace clang {
-namespace thread_safety {
+namespace threadSafety {
/// This enum distinguishes between different kinds of operations that may
/// need to be protected by locks. We use this enum in error handling.
enum ProtectedOperationKind {
POK_VarDereference, ///< Dereferencing a variable (e.g. p in *p = 5;)
POK_VarAccess, ///< Reading or writing a variable (e.g. x in x = 5;)
- POK_FunctionCall ///< Making a function call (e.g. fool())
+ POK_FunctionCall, ///< Making a function call (e.g. fool())
+ POK_PassByRef, ///< Passing a guarded variable by reference.
+ POK_PtPassByRef, ///< Passing a pt-guarded variable by reference.
};
/// This enum distinguishes between different kinds of lock actions. For
/// example, it is an error to write a variable protected by shared version of a
/// mutex.
enum LockKind {
- LK_Shared, ///< Shared/reader lock of a mutex.
+ LK_Shared, ///< Shared/reader lock of a mutex.
LK_Exclusive, ///< Exclusive/writer lock of a mutex.
- LK_Generic ///< Can be either Shared or Exclusive
+ LK_Generic ///< Can be either Shared or Exclusive
};
/// This enum distinguishes between different ways to access (read or write) a
@@ -161,6 +163,16 @@ public:
LockKind LK, SourceLocation Loc,
Name *PossibleMatch = nullptr) {}
+ /// Warn when acquiring a lock that the negative capability is not held.
+ /// \param Kind -- the capability's name parameter (role, mutex, etc).
+ /// \param LockName -- The name for the lock expression, to be printed in the
+ /// diagnostic.
+ /// \param Neg -- The name of the negative capability to be printed in the
+ /// diagnostic.
+ /// \param Loc -- The location of the protected operation.
+ virtual void handleNegativeNotHeld(StringRef Kind, Name LockName, Name Neg,
+ SourceLocation Loc) {}
+
/// Warn when a function is called while an excluded mutex is locked. For
/// example, the mutex may be locked inside the function.
/// \param Kind -- the capability's name parameter (role, mutex, etc).
@@ -171,6 +183,13 @@ public:
virtual void handleFunExcludesLock(StringRef Kind, Name FunName,
Name LockName, SourceLocation Loc) {}
+ /// Called by the analysis when starting analysis of a function.
+ /// Used to issue suggestions for changes to annotations.
+ virtual void enterFunction(const FunctionDecl *FD) {}
+
+ /// Called by the analysis when finishing analysis of a function.
+ virtual void leaveFunction(const FunctionDecl *FD) {}
+
bool issueBetaWarnings() { return IssueBetaWarnings; }
void setIssueBetaWarnings(bool b) { IssueBetaWarnings = b; }
@@ -190,5 +209,5 @@ void runThreadSafetyAnalysis(AnalysisDeclContext &AC,
/// of access.
LockKind getLockKindFromAccessKind(AccessKind AK);
-}} // end namespace clang::thread_safety
+}} // end namespace clang::threadSafety
#endif
diff --git a/include/clang/Analysis/Analyses/ThreadSafetyCommon.h b/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
index 09c614ca3e36..be81121c102b 100644
--- a/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
+++ b/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
@@ -19,21 +19,63 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_THREAD_SAFETY_COMMON_H
-#define LLVM_CLANG_THREAD_SAFETY_COMMON_H
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYCOMMON_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYCOMMON_H
#include "clang/Analysis/Analyses/PostOrderCFGView.h"
#include "clang/Analysis/Analyses/ThreadSafetyTIL.h"
+#include "clang/Analysis/Analyses/ThreadSafetyTraverse.h"
#include "clang/Analysis/AnalysisContext.h"
#include "clang/Basic/OperatorKinds.h"
-
#include <memory>
+#include <ostream>
+#include <sstream>
#include <vector>
namespace clang {
namespace threadSafety {
+
+// Various helper functions on til::SExpr
+namespace sx {
+
+inline bool equals(const til::SExpr *E1, const til::SExpr *E2) {
+ return til::EqualsComparator::compareExprs(E1, E2);
+}
+
+inline bool matches(const til::SExpr *E1, const til::SExpr *E2) {
+ // We treat a top-level wildcard as the "univsersal" lock.
+ // It matches everything for the purpose of checking locks, but not
+ // for unlocking them.
+ if (isa<til::Wildcard>(E1))
+ return isa<til::Wildcard>(E2);
+ if (isa<til::Wildcard>(E2))
+ return isa<til::Wildcard>(E1);
+
+ return til::MatchComparator::compareExprs(E1, E2);
+}
+
+inline bool partiallyMatches(const til::SExpr *E1, const til::SExpr *E2) {
+ const auto *PE1 = dyn_cast_or_null<til::Project>(E1);
+ if (!PE1)
+ return false;
+ const auto *PE2 = dyn_cast_or_null<til::Project>(E2);
+ if (!PE2)
+ return false;
+ return PE1->clangDecl() == PE2->clangDecl();
+}
+
+inline std::string toString(const til::SExpr *E) {
+ std::stringstream ss;
+ til::StdPrinter::print(E, ss);
+ return ss.str();
+}
+
+} // end namespace sx
+
+
+
// This class defines the interface of a clang CFG Visitor.
// CFGWalker will invoke the following methods.
// Note that methods are not virtual; the visitor is templatized.
@@ -206,6 +248,59 @@ private:
};
+
+
+class CapabilityExpr {
+ // TODO: move this back into ThreadSafety.cpp
+ // This is specific to thread safety. It is here because
+ // translateAttrExpr needs it, but that should be moved too.
+
+private:
+ const til::SExpr* CapExpr; ///< The capability expression.
+ bool Negated; ///< True if this is a negative capability
+
+public:
+ CapabilityExpr(const til::SExpr *E, bool Neg) : CapExpr(E), Negated(Neg) {}
+
+ const til::SExpr* sexpr() const { return CapExpr; }
+ bool negative() const { return Negated; }
+
+ CapabilityExpr operator!() const {
+ return CapabilityExpr(CapExpr, !Negated);
+ }
+
+ bool equals(const CapabilityExpr &other) const {
+ return (Negated == other.Negated) && sx::equals(CapExpr, other.CapExpr);
+ }
+
+ bool matches(const CapabilityExpr &other) const {
+ return (Negated == other.Negated) && sx::matches(CapExpr, other.CapExpr);
+ }
+
+ bool matchesUniv(const CapabilityExpr &CapE) const {
+ return isUniversal() || matches(CapE);
+ }
+
+ bool partiallyMatches(const CapabilityExpr &other) const {
+ return (Negated == other.Negated) &&
+ sx::partiallyMatches(CapExpr, other.CapExpr);
+ }
+
+ std::string toString() const {
+ if (Negated)
+ return "!" + sx::toString(CapExpr);
+ return sx::toString(CapExpr);
+ }
+
+ bool shouldIgnore() const { return CapExpr == nullptr; }
+
+ bool isInvalid() const { return sexpr() && isa<til::Undefined>(sexpr()); }
+
+ bool isUniversal() const { return sexpr() && isa<til::Wildcard>(sexpr()); }
+};
+
+
+
// Translate clang::Expr to til::SExpr.
class SExprBuilder {
public:
@@ -219,18 +314,16 @@ public:
/// should be evaluated; multiple calling contexts can be chained together
/// by the lock_returned attribute.
struct CallingContext {
+ CallingContext *Prev; // The previous context; or 0 if none.
const NamedDecl *AttrDecl; // The decl to which the attr is attached.
const Expr *SelfArg; // Implicit object argument -- e.g. 'this'
unsigned NumArgs; // Number of funArgs
const Expr *const *FunArgs; // Function arguments
- 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)
+ CallingContext(CallingContext *P, const NamedDecl *D = nullptr)
+ : Prev(P), AttrDecl(D), SelfArg(nullptr),
+ NumArgs(0), FunArgs(nullptr), SelfArrow(false)
{}
};
@@ -242,6 +335,13 @@ public:
SelfVar->setKind(til::Variable::VK_SFun);
}
+ // Translate a clang expression in an attribute to a til::SExpr.
+ // Constructs the context from D, DeclExp, and SelfDecl.
+ CapabilityExpr translateAttrExpr(const Expr *AttrExp, const NamedDecl *D,
+ const Expr *DeclExp, VarDecl *SelfD=nullptr);
+
+ CapabilityExpr translateAttrExpr(const Expr *AttrExp, CallingContext *Ctx);
+
// Translate a clang statement or expression to a TIL expression.
// Also performs substitution of variables; Ctx provides the context.
// Dispatches on the type of S.
@@ -262,7 +362,8 @@ private:
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 *translateCallExpr(const CallExpr *CE, CallingContext *Ctx,
+ const Expr *SelfE = nullptr);
til::SExpr *translateCXXMemberCallExpr(const CXXMemberCallExpr *ME,
CallingContext *Ctx);
til::SExpr *translateCXXOperatorCallExpr(const CXXOperatorCallExpr *OCE,
@@ -280,10 +381,8 @@ private:
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 *translateAbstractConditionalOperator(
+ const AbstractConditionalOperator *C, CallingContext *Ctx);
til::SExpr *translateDeclStmt(const DeclStmt *S, CallingContext *Ctx);
@@ -362,21 +461,24 @@ private:
void mergePhiNodesBackEdge(const CFGBlock *Blk);
private:
+ // Set to true when parsing capability expressions, which get translated
+ // inaccurately in order to hack around smart pointers etc.
+ static const bool CapabilityExprMode = true;
+
til::MemRegionRef Arena;
til::Variable *SelfVar; // Variable to use for 'this'. May be null.
- til::SCFG *Scfg;
+ 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;
+ std::vector<til::Phi*> CurrentArguments;
+ std::vector<til::SExpr*> CurrentInstructions;
+ std::vector<til::Phi*> IncompleteArgs;
til::BasicBlock *CurrentBB;
BlockInfo *CurrentBlockInfo;
};
diff --git a/include/clang/Analysis/Analyses/ThreadSafetyLogical.h b/include/clang/Analysis/Analyses/ThreadSafetyLogical.h
index c4f4b21aab12..bc78021343a4 100644
--- a/include/clang/Analysis/Analyses/ThreadSafetyLogical.h
+++ b/include/clang/Analysis/Analyses/ThreadSafetyLogical.h
@@ -10,8 +10,8 @@
// that are used as part of fact-checking capability expressions.
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_THREAD_SAFETY_LOGICAL_H
-#define LLVM_CLANG_THREAD_SAFETY_LOGICAL_H
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYLOGICAL_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYLOGICAL_H
#include "clang/Analysis/Analyses/ThreadSafetyTIL.h"
@@ -41,13 +41,13 @@ private:
};
class Terminal : public LExpr {
- til::SExprRef Expr;
+ til::SExpr *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(); }
+ const til::SExpr *expr() const { return Expr; }
+ til::SExpr *expr() { return Expr; }
static bool classof(const LExpr *E) { return E->kind() == LExpr::Terminal; }
};
@@ -104,5 +104,5 @@ bool LExpr::implies(const LExpr *RHS) const {
}
}
-#endif // LLVM_CLANG_THREAD_SAFETY_LOGICAL_H
+#endif
diff --git a/include/clang/Analysis/Analyses/ThreadSafetyOps.def b/include/clang/Analysis/Analyses/ThreadSafetyOps.def
index 6ebc95dbe9a7..0d2458b0c893 100644
--- a/include/clang/Analysis/Analyses/ThreadSafetyOps.def
+++ b/include/clang/Analysis/Analyses/ThreadSafetyOps.def
@@ -44,8 +44,11 @@ TIL_OPCODE_DEF(Cast)
TIL_OPCODE_DEF(SCFG)
TIL_OPCODE_DEF(BasicBlock)
TIL_OPCODE_DEF(Phi)
+
+// Terminator instructions
TIL_OPCODE_DEF(Goto)
TIL_OPCODE_DEF(Branch)
+TIL_OPCODE_DEF(Return)
// pseudo-terms
TIL_OPCODE_DEF(Identifier)
diff --git a/include/clang/Analysis/Analyses/ThreadSafetyTIL.h b/include/clang/Analysis/Analyses/ThreadSafetyTIL.h
index 8e4299ea70e8..2cd8c6d6d2d6 100644
--- a/include/clang/Analysis/Analyses/ThreadSafetyTIL.h
+++ b/include/clang/Analysis/Analyses/ThreadSafetyTIL.h
@@ -44,17 +44,16 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_THREAD_SAFETY_TIL_H
-#define LLVM_CLANG_THREAD_SAFETY_TIL_H
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTIL_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTIL_H
// All clang include dependencies for this file must be put in
// ThreadSafetyUtil.h.
#include "ThreadSafetyUtil.h"
-
-#include <stdint.h>
#include <algorithm>
#include <cassert>
#include <cstddef>
+#include <stdint.h>
#include <utility>
@@ -63,24 +62,27 @@ namespace threadSafety {
namespace til {
+/// Enum for the different distinct classes of SExpr
enum TIL_Opcode {
#define TIL_OPCODE_DEF(X) COP_##X,
#include "ThreadSafetyOps.def"
#undef TIL_OPCODE_DEF
};
+/// Opcode for unary arithmetic operations.
enum TIL_UnaryOpcode : unsigned char {
UOP_Minus, // -
UOP_BitNot, // ~
UOP_LogicNot // !
};
+/// Opcode for binary arithmetic operations.
enum TIL_BinaryOpcode : unsigned char {
+ BOP_Add, // +
+ BOP_Sub, // -
BOP_Mul, // *
BOP_Div, // /
BOP_Rem, // %
- BOP_Add, // +
- BOP_Sub, // -
BOP_Shl, // <<
BOP_Shr, // >>
BOP_BitAnd, // &
@@ -90,37 +92,42 @@ enum TIL_BinaryOpcode : unsigned char {
BOP_Neq, // !=
BOP_Lt, // <
BOP_Leq, // <=
- BOP_LogicAnd, // &&
- BOP_LogicOr // ||
+ BOP_LogicAnd, // && (no short-circuit)
+ BOP_LogicOr // || (no short-circuit)
};
+/// Opcode for cast operations.
enum TIL_CastOpcode : unsigned char {
CAST_none = 0,
CAST_extendNum, // extend precision of numeric type
CAST_truncNum, // truncate precision of numeric type
CAST_toFloat, // convert to floating point type
CAST_toInt, // convert to integer type
+ CAST_objToPtr // convert smart pointer to pointer (C++ only)
};
const TIL_Opcode COP_Min = COP_Future;
const TIL_Opcode COP_Max = COP_Branch;
const TIL_UnaryOpcode UOP_Min = UOP_Minus;
const TIL_UnaryOpcode UOP_Max = UOP_LogicNot;
-const TIL_BinaryOpcode BOP_Min = BOP_Mul;
+const TIL_BinaryOpcode BOP_Min = BOP_Add;
const TIL_BinaryOpcode BOP_Max = BOP_LogicOr;
const TIL_CastOpcode CAST_Min = CAST_none;
const TIL_CastOpcode CAST_Max = CAST_toInt;
+/// Return the name of a unary opcode.
StringRef getUnaryOpcodeString(TIL_UnaryOpcode Op);
+
+/// Return the name of a binary opcode.
StringRef getBinaryOpcodeString(TIL_BinaryOpcode Op);
-// ValueTypes are data types that can actually be held in registers.
-// All variables and expressions must have a 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.
+/// ValueTypes are data types that can actually be held in registers.
+/// All variables and expressions must have a value type.
+/// Pointer types are further subdivided into the various heap-allocated
+/// types, such as functions, records, etc.
+/// Structured types that are passed by value (e.g. complex numbers)
+/// require special handling; they use BT_ValueRef, and size ST_0.
struct ValueType {
enum BaseType : unsigned char {
BT_Void = 0,
@@ -246,8 +253,10 @@ inline ValueType ValueType::getValueType<void*>() {
}
+class BasicBlock;
+
-// Base class for AST nodes in the typed intermediate language.
+/// Base class for AST nodes in the typed intermediate language.
class SExpr {
public:
TIL_Opcode opcode() const { return static_cast<TIL_Opcode>(Opcode); }
@@ -266,71 +275,47 @@ public:
// 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.
+ /// 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;
+ /// Returns the instruction ID for this expression.
+ /// All basic block instructions have a unique ID (i.e. virtual register).
+ unsigned id() const { return SExprID; }
+
+ /// Returns the block, if this is an instruction in a basic block,
+ /// otherwise returns null.
+ BasicBlock* block() const { return Block; }
+
+ /// Set the basic block and instruction ID for this expression.
+ void setID(BasicBlock *B, unsigned id) { Block = B; SExprID = id; }
+
protected:
- SExpr(TIL_Opcode Op) : Opcode(Op), Reserved(0), Flags(0) {}
- SExpr(const SExpr &E) : Opcode(E.Opcode), Reserved(0), Flags(E.Flags) {}
+ SExpr(TIL_Opcode Op)
+ : Opcode(Op), Reserved(0), Flags(0), SExprID(0), Block(nullptr) {}
+ SExpr(const SExpr &E)
+ : Opcode(E.Opcode), Reserved(0), Flags(E.Flags), SExprID(0),
+ Block(nullptr) {}
const unsigned char Opcode;
unsigned char Reserved;
unsigned short Flags;
+ unsigned SExprID;
+ BasicBlock* Block;
private:
SExpr() LLVM_DELETED_FUNCTION;
- // SExpr objects must be created in an arena.
+ /// 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) {
@@ -342,62 +327,64 @@ namespace ThreadSafetyTIL {
// 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.
+/// 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
+ VK_Let, ///< Let-variable
+ VK_Fun, ///< Function parameter
+ VK_SFun ///< SFunction (self) parameter
};
- // 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);
+ Variable(StringRef s, SExpr *D = nullptr)
+ : SExpr(COP_Variable), Name(s), Definition(D), Cvdecl(nullptr) {
+ Flags = VK_Let;
+ }
+ Variable(SExpr *D, const clang::ValueDecl *Cvd = nullptr)
+ : SExpr(COP_Variable), Name(Cvd ? Cvd->getName() : "_x"),
+ Definition(D), Cvdecl(Cvd) {
+ Flags = VK_Let;
+ }
+ Variable(const Variable &Vd, SExpr *D) // rewrite constructor
+ : SExpr(Vd), Name(Vd.Name), Definition(D), Cvdecl(Vd.Cvdecl) {
+ Flags = Vd.kind();
+ }
+ /// Return the kind of variable (let, function param, or self)
VariableKind kind() const { return static_cast<VariableKind>(Flags); }
- 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(); }
+ /// Return the name of the variable, if any.
+ StringRef name() const { return Name; }
- void attachVar() const { ++NumUses; }
- void detachVar() const { assert(NumUses > 0); --NumUses; }
+ /// Return the clang declaration for this variable, if any.
+ const clang::ValueDecl *clangDecl() const { return Cvdecl; }
- unsigned getID() const { return Id; }
- unsigned getBlockID() const { return BlockID; }
+ /// Return the definition of the variable.
+ /// For let-vars, this is the setting expression.
+ /// For function and self parameters, it is the type of the variable.
+ SExpr *definition() { return Definition; }
+ const SExpr *definition() const { return Definition; }
- void setName(StringRef S) { Name = S; }
- void 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 setName(StringRef S) { Name = S; }
void setKind(VariableKind K) { Flags = K; }
+ void setDefinition(SExpr *E) { Definition = E; }
+ void setClangDecl(const clang::ValueDecl *VD) { Cvdecl = VD; }
template <class V>
typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
@@ -405,7 +392,8 @@ public:
return Vs.reduceVariableRef(this);
}
- template <class C> typename C::CType compare(Variable* E, C& Cmp) {
+ template <class C>
+ typename C::CType compare(const Variable* E, C& Cmp) const {
return Cmp.compareVariableRefs(this, E);
}
@@ -416,17 +404,13 @@ private:
friend class Let;
StringRef Name; // The name of the variable.
- SExprRef Definition; // The TIL type or definition
+ SExpr* 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.
+/// 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; }
@@ -437,25 +421,17 @@ public:
FS_done
};
- Future() :
- SExpr(COP_Future), Status(FS_pending), Result(nullptr), Location(nullptr)
- {}
+ Future() : SExpr(COP_Future), Status(FS_pending), Result(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;
- }
+public:
// A lazy rewriting strategy should subclass Future and override this method.
- virtual SExpr *create() { return nullptr; }
+ virtual SExpr *compute() { return nullptr; }
// Return the result of this future if it exists, otherwise return null.
- SExpr *maybeGetResult() {
+ SExpr *maybeGetResult() const {
return Result;
}
@@ -463,8 +439,7 @@ public:
SExpr *result() {
switch (Status) {
case FS_pending:
- force();
- return Result;
+ return force();
case FS_evaluating:
return nullptr; // infinite loop; illegal recursion.
case FS_done:
@@ -478,88 +453,22 @@ public:
return Vs.traverse(Result, Ctx);
}
- template <class C> typename C::CType compare(Future* E, C& Cmp) {
+ template <class C>
+ typename C::CType compare(const Future* E, C& Cmp) const {
if (!Result || !E->Result)
return Cmp.comparePointers(this, E);
return Cmp.compare(Result, E->Result);
}
private:
- // Force the future.
- inline void force();
+ SExpr* 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.
+/// Placeholder for expressions that cannot be represented in the TIL.
class Undefined : public SExpr {
public:
static bool classof(const SExpr *E) { return E->opcode() == COP_Undefined; }
@@ -572,8 +481,9 @@ public:
return Vs.reduceUndefined(*this);
}
- template <class C> typename C::CType compare(Undefined* E, C& Cmp) {
- return Cmp.comparePointers(Cstmt, E->Cstmt);
+ template <class C>
+ typename C::CType compare(const Undefined* E, C& Cmp) const {
+ return Cmp.trueResult();
}
private:
@@ -581,7 +491,7 @@ private:
};
-// Placeholder for a wildcard that matches any other expression.
+/// 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; }
@@ -593,7 +503,8 @@ public:
return Vs.reduceWildcard(*this);
}
- template <class C> typename C::CType compare(Wildcard* E, C& Cmp) {
+ template <class C>
+ typename C::CType compare(const Wildcard* E, C& Cmp) const {
return Cmp.trueResult();
}
};
@@ -626,9 +537,10 @@ public:
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);
+ template <class C>
+ typename C::CType compare(const Literal* E, C& Cmp) const {
+ // TODO: defer actual comparison to LiteralT
+ return Cmp.trueResult();
}
private:
@@ -710,8 +622,8 @@ typename V::R_SExpr Literal::traverse(V &Vs, typename V::R_Ctx Ctx) {
}
-// Literal pointer to an object allocated in memory.
-// At compile time, pointer literals are represented by symbolic names.
+/// A Literal pointer to an object allocated in memory.
+/// At compile time, pointer literals are represented by symbolic names.
class LiteralPtr : public SExpr {
public:
static bool classof(const SExpr *E) { return E->opcode() == COP_LiteralPtr; }
@@ -727,7 +639,8 @@ public:
return Vs.reduceLiteralPtr(*this);
}
- template <class C> typename C::CType compare(LiteralPtr* E, C& Cmp) {
+ template <class C>
+ typename C::CType compare(const LiteralPtr* E, C& Cmp) const {
return Cmp.comparePointers(Cvdecl, E->Cvdecl);
}
@@ -736,9 +649,9 @@ private:
};
-// 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)))
+/// A function -- a.k.a. lambda abstraction.
+/// Functions with multiple arguments are created by currying,
+/// e.g. (Function (x: Int) (Function (y: Int) (Code { return x + y })))
class Function : public SExpr {
public:
static bool classof(const SExpr *E) { return E->opcode() == COP_Function; }
@@ -755,8 +668,8 @@ public:
Variable *variableDecl() { return VarDecl; }
const Variable *variableDecl() const { return VarDecl; }
- SExpr *body() { return Body.get(); }
- const SExpr *body() const { return Body.get(); }
+ SExpr *body() { return Body; }
+ const SExpr *body() const { return Body; }
template <class V>
typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
@@ -769,7 +682,8 @@ public:
return Vs.reduceFunction(*this, Nvd, E1);
}
- template <class C> typename C::CType compare(Function* E, C& Cmp) {
+ template <class C>
+ typename C::CType compare(const Function* E, C& Cmp) const {
typename C::CType Ct =
Cmp.compare(VarDecl->definition(), E->VarDecl->definition());
if (Cmp.notTrue(Ct))
@@ -782,13 +696,13 @@ public:
private:
Variable *VarDecl;
- SExprRef Body;
+ SExpr* Body;
};
-// A self-applicable function.
-// A self-applicable function can be applied to itself. It's useful for
-// implementing objects and late binding
+/// 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; }
@@ -797,20 +711,20 @@ public:
: SExpr(COP_SFunction), VarDecl(Vd), Body(B) {
assert(Vd->Definition == nullptr);
Vd->setKind(Variable::VK_SFun);
- Vd->Definition.reset(this);
+ Vd->Definition = this;
}
SFunction(const SFunction &F, Variable *Vd, SExpr *B) // rewrite constructor
: SExpr(F), VarDecl(Vd), Body(B) {
assert(Vd->Definition == nullptr);
Vd->setKind(Variable::VK_SFun);
- Vd->Definition.reset(this);
+ Vd->Definition = this;
}
Variable *variableDecl() { return VarDecl; }
const Variable *variableDecl() const { return VarDecl; }
- SExpr *body() { return Body.get(); }
- const SExpr *body() const { return Body.get(); }
+ SExpr *body() { return Body; }
+ const SExpr *body() const { return Body; }
template <class V>
typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
@@ -824,7 +738,8 @@ public:
return Vs.reduceSFunction(*this, Nvd, E1);
}
- template <class C> typename C::CType compare(SFunction* E, C& Cmp) {
+ template <class C>
+ typename C::CType compare(const SFunction* E, C& Cmp) const {
Cmp.enterScope(variableDecl(), E->variableDecl());
typename C::CType Ct = Cmp.compare(body(), E->body());
Cmp.leaveScope();
@@ -833,11 +748,11 @@ public:
private:
Variable *VarDecl;
- SExprRef Body;
+ SExpr* Body;
};
-// A block of code -- e.g. the body of a function.
+/// 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; }
@@ -846,11 +761,11 @@ public:
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 *returnType() { return ReturnType; }
+ const SExpr *returnType() const { return ReturnType; }
- SExpr *body() { return Body.get(); }
- const SExpr *body() const { return Body.get(); }
+ SExpr *body() { return Body; }
+ const SExpr *body() const { return Body; }
template <class V>
typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
@@ -859,7 +774,8 @@ public:
return Vs.reduceCode(*this, Nt, Nb);
}
- template <class C> typename C::CType compare(Code* E, C& Cmp) {
+ template <class C>
+ typename C::CType compare(const Code* E, C& Cmp) const {
typename C::CType Ct = Cmp.compare(returnType(), E->returnType());
if (Cmp.notTrue(Ct))
return Ct;
@@ -867,12 +783,12 @@ public:
}
private:
- SExprRef ReturnType;
- SExprRef Body;
+ SExpr* ReturnType;
+ SExpr* Body;
};
-// A typed, writable location in memory
+/// A typed, writable location in memory
class Field : public SExpr {
public:
static bool classof(const SExpr *E) { return E->opcode() == COP_Field; }
@@ -881,11 +797,11 @@ public:
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 *range() { return Range; }
+ const SExpr *range() const { return Range; }
- SExpr *body() { return Body.get(); }
- const SExpr *body() const { return Body.get(); }
+ SExpr *body() { return Body; }
+ const SExpr *body() const { return Body; }
template <class V>
typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
@@ -894,7 +810,8 @@ public:
return Vs.reduceField(*this, Nr, Nb);
}
- template <class C> typename C::CType compare(Field* E, C& Cmp) {
+ template <class C>
+ typename C::CType compare(const Field* E, C& Cmp) const {
typename C::CType Ct = Cmp.compare(range(), E->range());
if (Cmp.notTrue(Ct))
return Ct;
@@ -902,12 +819,16 @@ public:
}
private:
- SExprRef Range;
- SExprRef Body;
+ SExpr* Range;
+ SExpr* Body;
};
-// Apply an argument to a function
+/// Apply an argument to a function.
+/// Note that this does not actually call the function. Functions are curried,
+/// so this returns a closure in which the first parameter has been applied.
+/// Once all parameters have been applied, Call can be used to invoke the
+/// function.
class Apply : public SExpr {
public:
static bool classof(const SExpr *E) { return E->opcode() == COP_Apply; }
@@ -917,11 +838,11 @@ public:
: SExpr(A), Fun(F), Arg(Ar)
{}
- SExpr *fun() { return Fun.get(); }
- const SExpr *fun() const { return Fun.get(); }
+ SExpr *fun() { return Fun; }
+ const SExpr *fun() const { return Fun; }
- SExpr *arg() { return Arg.get(); }
- const SExpr *arg() const { return Arg.get(); }
+ SExpr *arg() { return Arg; }
+ const SExpr *arg() const { return Arg; }
template <class V>
typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
@@ -930,7 +851,8 @@ public:
return Vs.reduceApply(*this, Nf, Na);
}
- template <class C> typename C::CType compare(Apply* E, C& Cmp) {
+ template <class C>
+ typename C::CType compare(const Apply* E, C& Cmp) const {
typename C::CType Ct = Cmp.compare(fun(), E->fun());
if (Cmp.notTrue(Ct))
return Ct;
@@ -938,12 +860,12 @@ public:
}
private:
- SExprRef Fun;
- SExprRef Arg;
+ SExpr* Fun;
+ SExpr* Arg;
};
-// Apply a self-argument to a self-applicable function
+/// 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; }
@@ -952,23 +874,24 @@ public:
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 *sfun() { return Sfun; }
+ const SExpr *sfun() const { return Sfun; }
- SExpr *arg() { return Arg.get() ? Arg.get() : Sfun.get(); }
- const SExpr *arg() const { return Arg.get() ? Arg.get() : Sfun.get(); }
+ SExpr *arg() { return Arg ? Arg : Sfun; }
+ const SExpr *arg() const { return Arg ? Arg : Sfun; }
- bool isDelegation() const { return Arg == nullptr; }
+ 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))
+ typename V::R_SExpr Na = Arg ? Vs.traverse(Arg, Vs.subExprCtx(Ctx))
: nullptr;
return Vs.reduceSApply(*this, Nf, Na);
}
- template <class C> typename C::CType compare(SApply* E, C& Cmp) {
+ template <class C>
+ typename C::CType compare(const SApply* E, C& Cmp) const {
typename C::CType Ct = Cmp.compare(sfun(), E->sfun());
if (Cmp.notTrue(Ct) || (!arg() && !E->arg()))
return Ct;
@@ -976,12 +899,12 @@ public:
}
private:
- SExprRef Sfun;
- SExprRef Arg;
+ SExpr* Sfun;
+ SExpr* Arg;
};
-// Project a named slot from a C++ struct or class.
+/// 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; }
@@ -989,17 +912,23 @@ public:
Project(SExpr *R, StringRef SName)
: SExpr(COP_Project), Rec(R), SlotName(SName), Cvdecl(nullptr)
{ }
- Project(SExpr *R, clang::ValueDecl *Cvd)
+ Project(SExpr *R, const clang::ValueDecl *Cvd)
: SExpr(COP_Project), Rec(R), SlotName(Cvd->getName()), Cvdecl(Cvd)
{ }
Project(const Project &P, SExpr *R)
: SExpr(P), Rec(R), SlotName(P.SlotName), Cvdecl(P.Cvdecl)
{ }
- SExpr *record() { return Rec.get(); }
- const SExpr *record() const { return Rec.get(); }
+ SExpr *record() { return Rec; }
+ const SExpr *record() const { return Rec; }
+
+ const clang::ValueDecl *clangDecl() const { return Cvdecl; }
- const clang::ValueDecl *clangValueDecl() const { return Cvdecl; }
+ bool isArrow() const { return (Flags & 0x01) != 0; }
+ void setArrow(bool b) {
+ if (b) Flags |= 0x01;
+ else Flags &= 0xFFFE;
+ }
StringRef slotName() const {
if (Cvdecl)
@@ -1014,7 +943,8 @@ public:
return Vs.reduceProject(*this, Nr);
}
- template <class C> typename C::CType compare(Project* E, C& Cmp) {
+ template <class C>
+ typename C::CType compare(const Project* E, C& Cmp) const {
typename C::CType Ct = Cmp.compare(record(), E->record());
if (Cmp.notTrue(Ct))
return Ct;
@@ -1022,13 +952,13 @@ public:
}
private:
- SExprRef Rec;
+ SExpr* Rec;
StringRef SlotName;
- clang::ValueDecl *Cvdecl;
+ const clang::ValueDecl *Cvdecl;
};
-// Call a function (after all arguments have been applied).
+/// 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; }
@@ -1037,8 +967,8 @@ public:
: 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(); }
+ SExpr *target() { return Target; }
+ const SExpr *target() const { return Target; }
const clang::CallExpr *clangCallExpr() const { return Cexpr; }
@@ -1048,17 +978,18 @@ public:
return Vs.reduceCall(*this, Nt);
}
- template <class C> typename C::CType compare(Call* E, C& Cmp) {
+ template <class C>
+ typename C::CType compare(const Call* E, C& Cmp) const {
return Cmp.compare(target(), E->target());
}
private:
- SExprRef Target;
+ SExpr* Target;
const clang::CallExpr *Cexpr;
};
-// Allocate memory for a new value on the heap or stack.
+/// 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; }
@@ -1073,8 +1004,8 @@ public:
AllocKind kind() const { return static_cast<AllocKind>(Flags); }
- SExpr *dataType() { return Dtype.get(); }
- const SExpr *dataType() const { return Dtype.get(); }
+ SExpr *dataType() { return Dtype; }
+ const SExpr *dataType() const { return Dtype; }
template <class V>
typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
@@ -1082,7 +1013,8 @@ public:
return Vs.reduceAlloc(*this, Nd);
}
- template <class C> typename C::CType compare(Alloc* E, C& Cmp) {
+ template <class C>
+ typename C::CType compare(const Alloc* E, C& Cmp) const {
typename C::CType Ct = Cmp.compareIntegers(kind(), E->kind());
if (Cmp.notTrue(Ct))
return Ct;
@@ -1090,11 +1022,11 @@ public:
}
private:
- SExprRef Dtype;
+ SExpr* Dtype;
};
-// Load a value from memory.
+/// Load a value from memory.
class Load : public SExpr {
public:
static bool classof(const SExpr *E) { return E->opcode() == COP_Load; }
@@ -1102,8 +1034,8 @@ public:
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(); }
+ SExpr *pointer() { return Ptr; }
+ const SExpr *pointer() const { return Ptr; }
template <class V>
typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
@@ -1111,17 +1043,18 @@ public:
return Vs.reduceLoad(*this, Np);
}
- template <class C> typename C::CType compare(Load* E, C& Cmp) {
+ template <class C>
+ typename C::CType compare(const Load* E, C& Cmp) const {
return Cmp.compare(pointer(), E->pointer());
}
private:
- SExprRef Ptr;
+ SExpr* Ptr;
};
-// Store a value to memory.
-// Source is a pointer, destination is the value to store.
+/// Store a value to memory.
+/// The destination is a pointer to a field, the source is the value to store.
class Store : public SExpr {
public:
static bool classof(const SExpr *E) { return E->opcode() == COP_Store; }
@@ -1129,11 +1062,11 @@ public:
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 *destination() { return Dest; } // Address to store to
+ const SExpr *destination() const { return Dest; }
- SExpr *source() { return Source.get(); } // Value to store
- const SExpr *source() const { return Source.get(); }
+ SExpr *source() { return Source; } // Value to store
+ const SExpr *source() const { return Source; }
template <class V>
typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
@@ -1142,7 +1075,8 @@ public:
return Vs.reduceStore(*this, Np, Nv);
}
- template <class C> typename C::CType compare(Store* E, C& Cmp) {
+ template <class C>
+ typename C::CType compare(const Store* E, C& Cmp) const {
typename C::CType Ct = Cmp.compare(destination(), E->destination());
if (Cmp.notTrue(Ct))
return Ct;
@@ -1150,13 +1084,13 @@ public:
}
private:
- SExprRef Dest;
- SExprRef Source;
+ SExpr* Dest;
+ SExpr* 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).
+/// If p is a reference to an array, then p[i] is a reference to the i'th
+/// element of the array.
class ArrayIndex : public SExpr {
public:
static bool classof(const SExpr *E) { return E->opcode() == COP_ArrayIndex; }
@@ -1165,11 +1099,11 @@ public:
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 *array() { return Array; }
+ const SExpr *array() const { return Array; }
- SExpr *index() { return Index.get(); }
- const SExpr *index() const { return Index.get(); }
+ SExpr *index() { return Index; }
+ const SExpr *index() const { return Index; }
template <class V>
typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
@@ -1178,7 +1112,8 @@ public:
return Vs.reduceArrayIndex(*this, Na, Ni);
}
- template <class C> typename C::CType compare(ArrayIndex* E, C& Cmp) {
+ template <class C>
+ typename C::CType compare(const ArrayIndex* E, C& Cmp) const {
typename C::CType Ct = Cmp.compare(array(), E->array());
if (Cmp.notTrue(Ct))
return Ct;
@@ -1186,14 +1121,14 @@ public:
}
private:
- SExprRef Array;
- SExprRef Index;
+ SExpr* Array;
+ SExpr* Index;
};
-// Pointer arithmetic, restricted to arrays only.
-// If p is a reference to an array, then p + n, where n is an integer, is
-// a reference to a subarray.
+/// 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; }
@@ -1202,11 +1137,11 @@ public:
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 *array() { return Array; }
+ const SExpr *array() const { return Array; }
- SExpr *index() { return Index.get(); }
- const SExpr *index() const { return Index.get(); }
+ SExpr *index() { return Index; }
+ const SExpr *index() const { return Index; }
template <class V>
typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
@@ -1215,7 +1150,8 @@ public:
return Vs.reduceArrayAdd(*this, Na, Ni);
}
- template <class C> typename C::CType compare(ArrayAdd* E, C& Cmp) {
+ template <class C>
+ typename C::CType compare(const ArrayAdd* E, C& Cmp) const {
typename C::CType Ct = Cmp.compare(array(), E->array());
if (Cmp.notTrue(Ct))
return Ct;
@@ -1223,12 +1159,13 @@ public:
}
private:
- SExprRef Array;
- SExprRef Index;
+ SExpr* Array;
+ SExpr* Index;
};
-// Simple unary operation -- e.g. !, ~, etc.
+/// Simple arithmetic unary operations, e.g. negate and not.
+/// These operations have no side-effects.
class UnaryOp : public SExpr {
public:
static bool classof(const SExpr *E) { return E->opcode() == COP_UnaryOp; }
@@ -1242,8 +1179,8 @@ public:
return static_cast<TIL_UnaryOpcode>(Flags);
}
- SExpr *expr() { return Expr0.get(); }
- const SExpr *expr() const { return Expr0.get(); }
+ SExpr *expr() { return Expr0; }
+ const SExpr *expr() const { return Expr0; }
template <class V>
typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
@@ -1251,7 +1188,8 @@ public:
return Vs.reduceUnaryOp(*this, Ne);
}
- template <class C> typename C::CType compare(UnaryOp* E, C& Cmp) {
+ template <class C>
+ typename C::CType compare(const UnaryOp* E, C& Cmp) const {
typename C::CType Ct =
Cmp.compareIntegers(unaryOpcode(), E->unaryOpcode());
if (Cmp.notTrue(Ct))
@@ -1260,11 +1198,12 @@ public:
}
private:
- SExprRef Expr0;
+ SExpr* Expr0;
};
-// Simple binary operation -- e.g. +, -, etc.
+/// Simple arithmetic binary operations, e.g. +, -, etc.
+/// These operations have no side effects.
class BinaryOp : public SExpr {
public:
static bool classof(const SExpr *E) { return E->opcode() == COP_BinaryOp; }
@@ -1282,11 +1221,11 @@ public:
return static_cast<TIL_BinaryOpcode>(Flags);
}
- SExpr *expr0() { return Expr0.get(); }
- const SExpr *expr0() const { return Expr0.get(); }
+ SExpr *expr0() { return Expr0; }
+ const SExpr *expr0() const { return Expr0; }
- SExpr *expr1() { return Expr1.get(); }
- const SExpr *expr1() const { return Expr1.get(); }
+ SExpr *expr1() { return Expr1; }
+ const SExpr *expr1() const { return Expr1; }
template <class V>
typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
@@ -1295,7 +1234,8 @@ public:
return Vs.reduceBinaryOp(*this, Ne0, Ne1);
}
- template <class C> typename C::CType compare(BinaryOp* E, C& Cmp) {
+ template <class C>
+ typename C::CType compare(const BinaryOp* E, C& Cmp) const {
typename C::CType Ct =
Cmp.compareIntegers(binaryOpcode(), E->binaryOpcode());
if (Cmp.notTrue(Ct))
@@ -1307,12 +1247,14 @@ public:
}
private:
- SExprRef Expr0;
- SExprRef Expr1;
+ SExpr* Expr0;
+ SExpr* Expr1;
};
-// Cast expression
+/// Cast expressions.
+/// Cast expressions are essentially unary operations, but we treat them
+/// as a distinct AST node because they only change the type of the result.
class Cast : public SExpr {
public:
static bool classof(const SExpr *E) { return E->opcode() == COP_Cast; }
@@ -1324,8 +1266,8 @@ public:
return static_cast<TIL_CastOpcode>(Flags);
}
- SExpr *expr() { return Expr0.get(); }
- const SExpr *expr() const { return Expr0.get(); }
+ SExpr *expr() { return Expr0; }
+ const SExpr *expr() const { return Expr0; }
template <class V>
typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
@@ -1333,7 +1275,8 @@ public:
return Vs.reduceCast(*this, Ne);
}
- template <class C> typename C::CType compare(Cast* E, C& Cmp) {
+ template <class C>
+ typename C::CType compare(const Cast* E, C& Cmp) const {
typename C::CType Ct =
Cmp.compareIntegers(castOpcode(), E->castOpcode());
if (Cmp.notTrue(Ct))
@@ -1342,16 +1285,18 @@ public:
}
private:
- SExprRef Expr0;
+ SExpr* Expr0;
};
class SCFG;
+/// Phi Node, for code in SSA form.
+/// Each Phi node has an array of possible values that it can take,
+/// depending on where control flow comes from.
class Phi : public SExpr {
public:
- // TODO: change to SExprRef
typedef SimpleArray<SExpr *> ValArray;
// In minimal SSA form, all Phi nodes are MultiVal.
@@ -1365,9 +1310,12 @@ public:
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)) {}
+ Phi()
+ : SExpr(COP_Phi), Cvdecl(nullptr) {}
+ Phi(MemRegionRef A, unsigned Nvals)
+ : SExpr(COP_Phi), Values(A, Nvals), Cvdecl(nullptr) {}
+ Phi(const Phi &P, ValArray &&Vs)
+ : SExpr(P), Values(std::move(Vs)), Cvdecl(nullptr) {}
const ValArray &values() const { return Values; }
ValArray &values() { return Values; }
@@ -1375,6 +1323,12 @@ public:
Status status() const { return static_cast<Status>(Flags); }
void setStatus(Status s) { Flags = s; }
+ /// Return the clang declaration of the variable for this Phi node, if any.
+ const clang::ValueDecl *clangDecl() const { return Cvdecl; }
+
+ /// Set the clang variable associated with this Phi node.
+ void setClangDecl(const clang::ValueDecl *Cvd) { Cvdecl = Cvd; }
+
template <class V>
typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
typename V::template Container<typename V::R_SExpr>
@@ -1386,72 +1340,268 @@ public:
return Vs.reducePhi(*this, Nvs);
}
- template <class C> typename C::CType compare(Phi *E, C &Cmp) {
+ template <class C>
+ typename C::CType compare(const Phi *E, C &Cmp) const {
// TODO: implement CFG comparisons
return Cmp.comparePointers(this, E);
}
private:
ValArray Values;
+ const clang::ValueDecl* Cvdecl;
+};
+
+
+/// Base class for basic block terminators: Branch, Goto, and Return.
+class Terminator : public SExpr {
+public:
+ static bool classof(const SExpr *E) {
+ return E->opcode() >= COP_Goto && E->opcode() <= COP_Return;
+ }
+
+protected:
+ Terminator(TIL_Opcode Op) : SExpr(Op) {}
+ Terminator(const SExpr &E) : SExpr(E) {}
+
+public:
+ /// Return the list of basic blocks that this terminator can branch to.
+ ArrayRef<BasicBlock*> successors();
+
+ ArrayRef<BasicBlock*> successors() const {
+ return const_cast<Terminator*>(this)->successors();
+ }
};
-// 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.
+/// Jump to another basic block.
+/// A goto instruction is essentially a tail-recursive call into another
+/// block. In addition to the block pointer, it specifies an index into the
+/// phi nodes of that block. The index can be used to retrieve the "arguments"
+/// of the call.
+class Goto : public Terminator {
+public:
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Goto; }
+
+ Goto(BasicBlock *B, unsigned I)
+ : Terminator(COP_Goto), TargetBlock(B), Index(I) {}
+ Goto(const Goto &G, BasicBlock *B, unsigned I)
+ : Terminator(COP_Goto), TargetBlock(B), Index(I) {}
+
+ const BasicBlock *targetBlock() const { return TargetBlock; }
+ BasicBlock *targetBlock() { return TargetBlock; }
+
+ /// Returns the index into the
+ unsigned index() const { return Index; }
+
+ /// Return the list of basic blocks that this terminator can branch to.
+ ArrayRef<BasicBlock*> successors() {
+ return ArrayRef<BasicBlock*>(&TargetBlock, 1);
+ }
+
+ template <class V>
+ typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
+ BasicBlock *Ntb = Vs.reduceBasicBlockRef(TargetBlock);
+ return Vs.reduceGoto(*this, Ntb);
+ }
+
+ template <class C>
+ typename C::CType compare(const Goto *E, C &Cmp) const {
+ // TODO: implement CFG comparisons
+ return Cmp.comparePointers(this, E);
+ }
+
+private:
+ BasicBlock *TargetBlock;
+ unsigned Index;
+};
+
+
+/// A conditional branch to two other blocks.
+/// Note that unlike Goto, Branch does not have an index. The target blocks
+/// must be child-blocks, and cannot have Phi nodes.
+class Branch : public Terminator {
+public:
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Branch; }
+
+ Branch(SExpr *C, BasicBlock *T, BasicBlock *E)
+ : Terminator(COP_Branch), Condition(C) {
+ Branches[0] = T;
+ Branches[1] = E;
+ }
+ Branch(const Branch &Br, SExpr *C, BasicBlock *T, BasicBlock *E)
+ : Terminator(Br), Condition(C) {
+ Branches[0] = T;
+ Branches[1] = E;
+ }
+
+ const SExpr *condition() const { return Condition; }
+ SExpr *condition() { return Condition; }
+
+ const BasicBlock *thenBlock() const { return Branches[0]; }
+ BasicBlock *thenBlock() { return Branches[0]; }
+
+ const BasicBlock *elseBlock() const { return Branches[1]; }
+ BasicBlock *elseBlock() { return Branches[1]; }
+
+ /// Return the list of basic blocks that this terminator can branch to.
+ ArrayRef<BasicBlock*> successors() {
+ return ArrayRef<BasicBlock*>(Branches, 2);
+ }
+
+ template <class V>
+ typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
+ auto Nc = Vs.traverse(Condition, Vs.subExprCtx(Ctx));
+ BasicBlock *Ntb = Vs.reduceBasicBlockRef(Branches[0]);
+ BasicBlock *Nte = Vs.reduceBasicBlockRef(Branches[1]);
+ return Vs.reduceBranch(*this, Nc, Ntb, Nte);
+ }
+
+ template <class C>
+ typename C::CType compare(const Branch *E, C &Cmp) const {
+ // TODO: implement CFG comparisons
+ return Cmp.comparePointers(this, E);
+ }
+
+private:
+ SExpr* Condition;
+ BasicBlock *Branches[2];
+};
+
+
+/// Return from the enclosing function, passing the return value to the caller.
+/// Only the exit block should end with a return statement.
+class Return : public Terminator {
+public:
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Return; }
+
+ Return(SExpr* Rval) : Terminator(COP_Return), Retval(Rval) {}
+ Return(const Return &R, SExpr* Rval) : Terminator(R), Retval(Rval) {}
+
+ /// Return an empty list.
+ ArrayRef<BasicBlock*> successors() {
+ return ArrayRef<BasicBlock*>();
+ }
+
+ SExpr *returnValue() { return Retval; }
+ const SExpr *returnValue() const { return Retval; }
+
+ template <class V>
+ typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
+ auto Ne = Vs.traverse(Retval, Vs.subExprCtx(Ctx));
+ return Vs.reduceReturn(*this, Ne);
+ }
+
+ template <class C>
+ typename C::CType compare(const Return *E, C &Cmp) const {
+ return Cmp.compare(Retval, E->Retval);
+ }
+
+private:
+ SExpr* Retval;
+};
+
+
+inline ArrayRef<BasicBlock*> Terminator::successors() {
+ switch (opcode()) {
+ case COP_Goto: return cast<Goto>(this)->successors();
+ case COP_Branch: return cast<Branch>(this)->successors();
+ case COP_Return: return cast<Return>(this)->successors();
+ default:
+ return ArrayRef<BasicBlock*>();
+ }
+}
+
+
+/// A basic block is part of an SCFG. It can be treated as a function in
+/// continuation passing style. A block consists of a sequence of phi nodes,
+/// which are "arguments" to the function, followed by a sequence of
+/// instructions. It ends with a Terminator, which is a Branch or Goto to
+/// another basic block in the same SCFG.
class BasicBlock : public SExpr {
public:
- typedef SimpleArray<Variable*> VarArray;
+ typedef SimpleArray<SExpr*> InstrArray;
typedef SimpleArray<BasicBlock*> BlockArray;
+ // TopologyNodes are used to overlay tree structures on top of the CFG,
+ // such as dominator and postdominator trees. Each block is assigned an
+ // ID in the tree according to a depth-first search. Tree traversals are
+ // always up, towards the parents.
+ struct TopologyNode {
+ TopologyNode() : NodeID(0), SizeOfSubTree(0), Parent(nullptr) {}
+
+ bool isParentOf(const TopologyNode& OtherNode) {
+ return OtherNode.NodeID > NodeID &&
+ OtherNode.NodeID < NodeID + SizeOfSubTree;
+ }
+
+ bool isParentOfOrEqual(const TopologyNode& OtherNode) {
+ return OtherNode.NodeID >= NodeID &&
+ OtherNode.NodeID < NodeID + SizeOfSubTree;
+ }
+
+ int NodeID;
+ int SizeOfSubTree; // Includes this node, so must be > 1.
+ BasicBlock *Parent; // Pointer to parent.
+ };
+
static bool classof(const SExpr *E) { return E->opcode() == COP_BasicBlock; }
- explicit BasicBlock(MemRegionRef A, BasicBlock* P = nullptr)
+ explicit BasicBlock(MemRegionRef A)
: 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)
- { }
+ Visited(0), TermInstr(nullptr) {}
+ BasicBlock(BasicBlock &B, MemRegionRef A, InstrArray &&As, InstrArray &&Is,
+ Terminator *T)
+ : SExpr(COP_BasicBlock), Arena(A), CFGPtr(nullptr), BlockID(0),Visited(0),
+ Args(std::move(As)), Instrs(std::move(Is)), TermInstr(T) {}
+
+ /// Returns the block ID. Every block has a unique ID in the CFG.
+ int blockID() const { return BlockID; }
- unsigned blockID() const { return BlockID; }
- unsigned numPredecessors() const { return Predecessors.size(); }
+ /// Returns the number of predecessors.
+ size_t numPredecessors() const { return Predecessors.size(); }
+ size_t numSuccessors() const { return successors().size(); }
const SCFG* cfg() const { return CFGPtr; }
SCFG* cfg() { return CFGPtr; }
- const BasicBlock *parent() const { return Parent; }
- BasicBlock *parent() { return Parent; }
+ const BasicBlock *parent() const { return DominatorNode.Parent; }
+ BasicBlock *parent() { return DominatorNode.Parent; }
- const VarArray &arguments() const { return Args; }
- VarArray &arguments() { return Args; }
+ const InstrArray &arguments() const { return Args; }
+ InstrArray &arguments() { return Args; }
- const VarArray &instructions() const { return Instrs; }
- VarArray &instructions() { return Instrs; }
+ InstrArray &instructions() { return Instrs; }
+ const InstrArray &instructions() const { return Instrs; }
- const BlockArray &predecessors() const { return Predecessors; }
+ /// Returns a list of predecessors.
+ /// The order of predecessors in the list is important; each phi node has
+ /// exactly one argument for each precessor, in the same order.
BlockArray &predecessors() { return Predecessors; }
+ const BlockArray &predecessors() const { return Predecessors; }
+
+ ArrayRef<BasicBlock*> successors() { return TermInstr->successors(); }
+ ArrayRef<BasicBlock*> successors() const { return TermInstr->successors(); }
+
+ const Terminator *terminator() const { return TermInstr; }
+ Terminator *terminator() { return TermInstr; }
- const SExpr *terminator() const { return Terminator.get(); }
- SExpr *terminator() { return Terminator.get(); }
+ void setTerminator(Terminator *E) { TermInstr = E; }
- void setBlockID(unsigned i) { BlockID = i; }
- void setParent(BasicBlock *P) { Parent = P; }
- void setTerminator(SExpr *E) { Terminator.reset(E); }
+ bool Dominates(const BasicBlock &Other) {
+ return DominatorNode.isParentOfOrEqual(Other.DominatorNode);
+ }
+
+ bool PostDominates(const BasicBlock &Other) {
+ return PostDominatorNode.isParentOfOrEqual(Other.PostDominatorNode);
+ }
- // Add a new argument. V must define a phi-node.
- void addArgument(Variable *V) {
- V->setKind(Variable::VK_LetBB);
+ /// Add a new argument.
+ void addArgument(Phi *V) {
Args.reserveCheck(1, Arena);
Args.push_back(V);
}
- // Add a new instruction.
- void addInstruction(Variable *V) {
- V->setKind(Variable::VK_LetBB);
+ /// Add a new instruction.
+ void addInstruction(SExpr *V) {
Instrs.reserveCheck(1, Arena);
Instrs.push_back(V);
}
@@ -1468,34 +1618,29 @@ public:
// 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.
+ /// 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());
+ typename V::template Container<SExpr*> Nas(Vs, Args.size());
+ typename V::template Container<SExpr*> Nis(Vs, Instrs.size());
// Entering the basic block should do any scope initialization.
Vs.enterBasicBlock(*this);
- for (auto *A : Args) {
- auto Ne = Vs.traverse(A->Definition, Vs.subExprCtx(Ctx));
- Variable *Nvd = Vs.enterScope(*A, Ne);
- Nas.push_back(Nvd);
+ for (auto *E : Args) {
+ auto Ne = Vs.traverse(E, Vs.subExprCtx(Ctx));
+ Nas.push_back(Ne);
}
- for (auto *I : Instrs) {
- auto Ne = Vs.traverse(I->Definition, Vs.subExprCtx(Ctx));
- Variable *Nvd = Vs.enterScope(*I, Ne);
- Nis.push_back(Nvd);
+ for (auto *E : Instrs) {
+ auto Ne = Vs.traverse(E, Vs.subExprCtx(Ctx));
+ Nis.push_back(Ne);
}
- auto Nt = Vs.traverse(Terminator, Ctx);
+ auto Nt = Vs.traverse(TermInstr, Ctx);
// Exiting the basic block should handle any scope cleanup.
Vs.exitBasicBlock(*this);
@@ -1503,7 +1648,8 @@ public:
return Vs.reduceBasicBlock(*this, Nas, Nis, Nt);
}
- template <class C> typename C::CType compare(BasicBlock *E, C &Cmp) {
+ template <class C>
+ typename C::CType compare(const BasicBlock *E, C &Cmp) const {
// TODO: implement CFG comparisons
return Cmp.comparePointers(this, E);
}
@@ -1511,22 +1657,32 @@ public:
private:
friend class SCFG;
- MemRegionRef Arena;
+ int renumberInstrs(int id); // assign unique ids to all instructions
+ int topologicalSort(SimpleArray<BasicBlock*>& Blocks, int ID);
+ int topologicalFinalSort(SimpleArray<BasicBlock*>& Blocks, int ID);
+ void computeDominator();
+ void computePostDominator();
- 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
+private:
+ MemRegionRef Arena; // The arena used to allocate this block.
+ SCFG *CFGPtr; // The CFG that contains this block.
+ int BlockID : 31; // unique id for this BB in the containing CFG.
+ // IDs are in topological order.
+ bool Visited : 1; // Bit to determine if a block has been visited
+ // during a traversal.
+ BlockArray Predecessors; // Predecessor blocks in the CFG.
+ InstrArray Args; // Phi nodes. One argument per predecessor.
+ InstrArray Instrs; // Instructions.
+ Terminator* TermInstr; // Terminating instruction
+
+ TopologyNode DominatorNode; // The dominator tree
+ TopologyNode PostDominatorNode; // The post-dominator tree
};
-// An SCFG is a control-flow graph. It consists of a set of basic blocks, each
-// of which terminates in a branch to another basic block. There is one
-// entry point, and one exit point.
+/// 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;
@@ -1537,20 +1693,29 @@ public:
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());
+ Entry(nullptr), Exit(nullptr), NumInstructions(0), Normal(false) {
+ Entry = new (A) BasicBlock(A);
+ Exit = new (A) BasicBlock(A);
+ auto *V = new (A) Phi();
Exit->addArgument(V);
+ Exit->setTerminator(new (A) Return(V));
add(Entry);
add(Exit);
}
SCFG(const SCFG &Cfg, BlockArray &&Ba) // steals memory from Ba
: SExpr(COP_SCFG), Arena(Cfg.Arena), Blocks(std::move(Ba)),
- Entry(nullptr), Exit(nullptr) {
+ Entry(nullptr), Exit(nullptr), NumInstructions(0), Normal(false) {
// TODO: set entry and exit!
}
+ /// Return true if this CFG is valid.
+ bool valid() const { return Entry && Exit && Blocks.size() > 0; }
+
+ /// Return true if this CFG has been normalized.
+ /// After normalization, blocks are in topological order, and block and
+ /// instruction IDs have been assigned.
+ bool normal() const { return Normal; }
+
iterator begin() { return Blocks.begin(); }
iterator end() { return Blocks.end(); }
@@ -1565,9 +1730,17 @@ public:
const BasicBlock *exit() const { return Exit; }
BasicBlock *exit() { return Exit; }
+ /// Return the number of blocks in the CFG.
+ /// Block::blockID() will return a number less than numBlocks();
+ size_t numBlocks() const { return Blocks.size(); }
+
+ /// Return the total number of instructions in the CFG.
+ /// This is useful for building instruction side-tables;
+ /// A call to SExpr::id() will return a number less than numInstructions().
+ unsigned numInstructions() { return NumInstructions; }
+
inline void add(BasicBlock *BB) {
- assert(BB->CFGPtr == nullptr || BB->CFGPtr == this);
- BB->setBlockID(Blocks.size());
+ assert(BB->CFGPtr == nullptr);
BB->CFGPtr = this;
Blocks.reserveCheck(1, Arena);
Blocks.push_back(BB);
@@ -1576,13 +1749,13 @@ public:
void setEntry(BasicBlock *BB) { Entry = BB; }
void setExit(BasicBlock *BB) { Exit = BB; }
- // Set varable ids in all blocks.
- void renumberVars();
+ void computeNormalForm();
template <class V>
typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
Vs.enterCFG(*this);
typename V::template Container<BasicBlock *> Bbs(Vs, Blocks.size());
+
for (auto *B : Blocks) {
Bbs.push_back( B->traverse(Vs, Vs.subExprCtx(Ctx)) );
}
@@ -1590,100 +1763,28 @@ public:
return Vs.reduceSCFG(*this, Bbs);
}
- template <class C> typename C::CType compare(SCFG *E, C &Cmp) {
- // TODO -- implement CFG comparisons
+ template <class C>
+ typename C::CType compare(const SCFG *E, C &Cmp) const {
+ // TODO: implement CFG comparisons
return Cmp.comparePointers(this, E);
}
private:
+ void renumberInstrs(); // assign unique ids to all instructions
+
+private:
MemRegionRef Arena;
BlockArray Blocks;
BasicBlock *Entry;
BasicBlock *Exit;
+ unsigned NumInstructions;
+ bool Normal;
};
-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.
+/// 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; }
@@ -1698,7 +1799,8 @@ public:
return Vs.reduceIdentifier(*this);
}
- template <class C> typename C::CType compare(Identifier* E, C& Cmp) {
+ template <class C>
+ typename C::CType compare(const Identifier* E, C& Cmp) const {
return Cmp.compareStrings(name(), E->name());
}
@@ -1707,8 +1809,8 @@ private:
};
-// An if-then-else expression.
-// This is a pseduo-term; it will be lowered to a branch in a CFG.
+/// 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; }
@@ -1720,14 +1822,14 @@ public:
: 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 *condition() { return Condition; } // Address to store to
+ const SExpr *condition() const { return Condition; }
- SExpr *thenExpr() { return ThenExpr.get(); } // Value to store
- const SExpr *thenExpr() const { return ThenExpr.get(); }
+ SExpr *thenExpr() { return ThenExpr; } // Value to store
+ const SExpr *thenExpr() const { return ThenExpr; }
- SExpr *elseExpr() { return ElseExpr.get(); } // Value to store
- const SExpr *elseExpr() const { return ElseExpr.get(); }
+ SExpr *elseExpr() { return ElseExpr; } // Value to store
+ const SExpr *elseExpr() const { return ElseExpr; }
template <class V>
typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
@@ -1737,7 +1839,8 @@ public:
return Vs.reduceIfThenElse(*this, Nc, Nt, Ne);
}
- template <class C> typename C::CType compare(IfThenElse* E, C& Cmp) {
+ template <class C>
+ typename C::CType compare(const IfThenElse* E, C& Cmp) const {
typename C::CType Ct = Cmp.compare(condition(), E->condition());
if (Cmp.notTrue(Ct))
return Ct;
@@ -1748,14 +1851,14 @@ public:
}
private:
- SExprRef Condition;
- SExprRef ThenExpr;
- SExprRef ElseExpr;
+ SExpr* Condition;
+ SExpr* ThenExpr;
+ SExpr* ElseExpr;
};
-// A let-expression, e.g. let x=t; u.
-// This is a pseduo-term; it will be lowered to instructions in a CFG.
+/// 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; }
@@ -1770,8 +1873,8 @@ public:
Variable *variableDecl() { return VarDecl; }
const Variable *variableDecl() const { return VarDecl; }
- SExpr *body() { return Body.get(); }
- const SExpr *body() const { return Body.get(); }
+ SExpr *body() { return Body; }
+ const SExpr *body() const { return Body; }
template <class V>
typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
@@ -1784,7 +1887,8 @@ public:
return Vs.reduceLet(*this, Nvd, E1);
}
- template <class C> typename C::CType compare(Let* E, C& Cmp) {
+ template <class C>
+ typename C::CType compare(const Let* E, C& Cmp) const {
typename C::CType Ct =
Cmp.compare(VarDecl->definition(), E->VarDecl->definition());
if (Cmp.notTrue(Ct))
@@ -1797,17 +1901,18 @@ public:
private:
Variable *VarDecl;
- SExprRef Body;
+ SExpr* Body;
};
-SExpr *getCanonicalVal(SExpr *E);
-void simplifyIncompleteArg(Variable *V, til::Phi *Ph);
+const SExpr *getCanonicalVal(const SExpr *E);
+SExpr* simplifyToCanonicalVal(SExpr *E);
+void simplifyIncompleteArg(til::Phi *Ph);
} // end namespace til
} // end namespace threadSafety
} // end namespace clang
-#endif // LLVM_CLANG_THREAD_SAFETY_TIL_H
+#endif
diff --git a/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h b/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h
index bc1490b4a448..705fe910d092 100644
--- a/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h
+++ b/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h
@@ -14,10 +14,11 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_THREAD_SAFETY_TRAVERSE_H
-#define LLVM_CLANG_THREAD_SAFETY_TRAVERSE_H
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTRAVERSE_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTRAVERSE_H
#include "ThreadSafetyTIL.h"
+#include <ostream>
namespace clang {
namespace threadSafety {
@@ -56,11 +57,16 @@ public:
// 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);
+ // E is a reference, so this can be use for in-place updates.
+ // The type T must be a subclass of SExpr.
+ template <class T>
+ typename R::R_SExpr traverse(T* &E, typename R::R_Ctx Ctx) {
+ return traverseSExpr(E, Ctx);
}
- typename R::R_SExpr traverse(SExpr *E, typename R::R_Ctx Ctx) {
+ // Override this method to do something for every expression.
+ // Does not allow in-place updates.
+ typename R::R_SExpr traverseSExpr(SExpr *E, typename R::R_Ctx Ctx) {
return traverseByCase(E, Ctx);
}
@@ -73,6 +79,7 @@ public:
#include "ThreadSafetyOps.def"
#undef TIL_OPCODE_DEF
}
+ return self()->reduceNull();
}
// Traverse e, by static dispatch on the type "X" of e.
@@ -90,10 +97,10 @@ public:
class SimpleReducerBase {
public:
enum TraversalKind {
- TRV_Normal,
- TRV_Decl,
- TRV_Lazy,
- TRV_Type
+ TRV_Normal, // ordinary subexpressions
+ TRV_Decl, // declarations (e.g. function bodies)
+ TRV_Lazy, // expressions that require lazy evaluation
+ TRV_Type // type expressions
};
// R_Ctx defines a "context" for the traversal, which encodes information
@@ -145,153 +152,6 @@ protected:
};
-// 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:
@@ -366,8 +226,8 @@ public:
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) {
+ R_BasicBlock reduceBasicBlock(BasicBlock &Orig, Container<R_SExpr> &As,
+ Container<R_SExpr> &Is, R_SExpr T) {
return (As.Success && Is.Success && T);
}
R_SExpr reducePhi(Phi &Orig, Container<R_SExpr> &As) {
@@ -379,6 +239,9 @@ public:
R_SExpr reduceBranch(Branch &O, R_SExpr C, BasicBlock *B0, BasicBlock *B1) {
return C;
}
+ R_SExpr reduceReturn(Return &O, R_SExpr E) {
+ return E;
+ }
R_SExpr reduceIdentifier(Identifier &Orig) {
return true;
@@ -423,7 +286,7 @@ protected:
Self *self() { return reinterpret_cast<Self *>(this); }
public:
- bool compareByCase(SExpr *E1, SExpr* E2) {
+ bool compareByCase(const SExpr *E1, const SExpr* E2) {
switch (E1->opcode()) {
#define TIL_OPCODE_DEF(X) \
case COP_##X: \
@@ -431,6 +294,7 @@ public:
#include "ThreadSafetyOps.def"
#undef TIL_OPCODE_DEF
}
+ return false;
}
};
@@ -449,38 +313,86 @@ public:
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) {
+ bool compare(const SExpr *E1, const SExpr* E2) {
if (E1->opcode() != E2->opcode())
return false;
return compareByCase(E1, E2);
}
// TODO -- handle alpha-renaming of variables
- void enterScope(Variable* V1, Variable* V2) { }
+ void enterScope(const Variable* V1, const Variable* V2) { }
void leaveScope() { }
- bool compareVariableRefs(Variable* V1, Variable* V2) {
+ bool compareVariableRefs(const Variable* V1, const Variable* V2) {
return V1 == V2;
}
- static bool compareExprs(SExpr *E1, SExpr* E2) {
+ static bool compareExprs(const SExpr *E1, const SExpr* E2) {
EqualsComparator Eq;
return Eq.compare(E1, E2);
}
};
+
+class MatchComparator : public Comparator<MatchComparator> {
+public:
+ // Result type for the comparison, e.g. bool for simple equality,
+ // or int for lexigraphic comparison (-1, 0, 1). Must have one value which
+ // denotes "true".
+ typedef bool CType;
+
+ CType trueResult() { return true; }
+ bool notTrue(CType ct) { return !ct; }
+
+ bool compareIntegers(unsigned i, unsigned j) { return i == j; }
+ bool compareStrings (StringRef s, StringRef r) { return s == r; }
+ bool comparePointers(const void* P, const void* Q) { return P == Q; }
+
+ bool compare(const SExpr *E1, const SExpr* E2) {
+ // Wildcards match anything.
+ if (E1->opcode() == COP_Wildcard || E2->opcode() == COP_Wildcard)
+ return true;
+ // otherwise normal equality.
+ if (E1->opcode() != E2->opcode())
+ return false;
+ return compareByCase(E1, E2);
+ }
+
+ // TODO -- handle alpha-renaming of variables
+ void enterScope(const Variable* V1, const Variable* V2) { }
+ void leaveScope() { }
+
+ bool compareVariableRefs(const Variable* V1, const Variable* V2) {
+ return V1 == V2;
+ }
+
+ static bool compareExprs(const SExpr *E1, const SExpr* E2) {
+ MatchComparator Matcher;
+ return Matcher.compare(E1, E2);
+ }
+};
+
+
+
+// inline std::ostream& operator<<(std::ostream& SS, StringRef R) {
+// return SS.write(R.data(), R.size());
+// }
+
// Pretty printer for TIL expressions
template <typename Self, typename StreamType>
class PrettyPrinter {
private:
bool Verbose; // Print out additional information
bool Cleanup; // Omit redundant decls.
+ bool CStyle; // Print exprs in C-like syntax.
public:
- PrettyPrinter(bool V = false, bool C = true) : Verbose(V), Cleanup(C) { }
+ PrettyPrinter(bool V = false, bool C = true, bool CS = true)
+ : Verbose(V), Cleanup(C), CStyle(CS)
+ {}
- static void print(SExpr *E, StreamType &SS) {
+ static void print(const SExpr *E, StreamType &SS) {
Self printer;
printer.printSExpr(E, SS, Prec_MAX);
}
@@ -502,7 +414,7 @@ protected:
static const unsigned Prec_MAX = 6;
// Return the precedence of a given node, for use in pretty printing.
- unsigned precedence(SExpr *E) {
+ unsigned precedence(const SExpr *E) {
switch (E->opcode()) {
case COP_Future: return Prec_Atom;
case COP_Undefined: return Prec_Atom;
@@ -529,13 +441,14 @@ protected:
case COP_UnaryOp: return Prec_Unary;
case COP_BinaryOp: return Prec_Binary;
- case COP_Cast: return Prec_Unary;
+ case COP_Cast: return Prec_Atom;
case COP_SCFG: return Prec_Decl;
case COP_BasicBlock: return Prec_MAX;
case COP_Phi: return Prec_Atom;
case COP_Goto: return Prec_Atom;
case COP_Branch: return Prec_Atom;
+ case COP_Return: return Prec_Other;
case COP_Identifier: return Prec_Atom;
case COP_IfThenElse: return Prec_Other;
@@ -544,22 +457,29 @@ protected:
return Prec_MAX;
}
- void printBlockLabel(StreamType & SS, BasicBlock *BB, unsigned index) {
+ void printBlockLabel(StreamType & SS, const BasicBlock *BB, int index) {
if (!BB) {
SS << "BB_null";
return;
}
SS << "BB_";
SS << BB->blockID();
- SS << ":";
- SS << index;
+ if (index >= 0) {
+ SS << ":";
+ SS << index;
+ }
}
- void printSExpr(SExpr *E, StreamType &SS, unsigned P) {
+
+ void printSExpr(const SExpr *E, StreamType &SS, unsigned P, bool Sub=true) {
if (!E) {
self()->printNull(SS);
return;
}
+ if (Sub && E->block() && E->opcode() != COP_Variable) {
+ SS << "_x" << E->id();
+ return;
+ }
if (self()->precedence(E) > P) {
// Wrap expr in () if necessary.
SS << "(";
@@ -582,28 +502,28 @@ protected:
SS << "#null";
}
- void printFuture(Future *E, StreamType &SS) {
+ void printFuture(const Future *E, StreamType &SS) {
self()->printSExpr(E->maybeGetResult(), SS, Prec_Atom);
}
- void printUndefined(Undefined *E, StreamType &SS) {
+ void printUndefined(const Undefined *E, StreamType &SS) {
SS << "#undefined";
}
- void printWildcard(Wildcard *E, StreamType &SS) {
- SS << "_";
+ void printWildcard(const Wildcard *E, StreamType &SS) {
+ SS << "*";
}
template<class T>
- void printLiteralT(LiteralT<T> *E, StreamType &SS) {
+ void printLiteralT(const LiteralT<T> *E, StreamType &SS) {
SS << E->value();
}
- void printLiteralT(LiteralT<uint8_t> *E, StreamType &SS) {
+ void printLiteralT(const LiteralT<uint8_t> *E, StreamType &SS) {
SS << "'" << E->value() << "'";
}
- void printLiteral(Literal *E, StreamType &SS) {
+ void printLiteral(const Literal *E, StreamType &SS) {
if (E->clangExpr()) {
SS << getSourceLiteralString(E->clangExpr());
return;
@@ -685,25 +605,18 @@ protected:
SS << "#lit";
}
- void printLiteralPtr(LiteralPtr *E, StreamType &SS) {
+ void printLiteralPtr(const 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();
+ void printVariable(const Variable *V, StreamType &SS, bool IsVarDecl=false) {
+ if (CStyle && V->kind() == Variable::VK_SFun)
+ SS << "this";
else
- SS << V->name() << V->getID();
+ SS << V->name() << V->id();
}
- void printFunction(Function *E, StreamType &SS, unsigned sugared = 0) {
+ void printFunction(const Function *E, StreamType &SS, unsigned sugared = 0) {
switch (sugared) {
default:
SS << "\\("; // Lambda
@@ -719,7 +632,7 @@ protected:
SS << ": ";
self()->printSExpr(E->variableDecl()->definition(), SS, Prec_MAX);
- SExpr *B = E->body();
+ const SExpr *B = E->body();
if (B && B->opcode() == COP_Function)
self()->printFunction(cast<Function>(B), SS, 2);
else {
@@ -728,29 +641,29 @@ protected:
}
}
- void printSFunction(SFunction *E, StreamType &SS) {
+ void printSFunction(const 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) {
+ void printCode(const Code *E, StreamType &SS) {
SS << ": ";
self()->printSExpr(E->returnType(), SS, Prec_Decl-1);
SS << " -> ";
self()->printSExpr(E->body(), SS, Prec_Decl);
}
- void printField(Field *E, StreamType &SS) {
+ void printField(const Field *E, StreamType &SS) {
SS << ": ";
self()->printSExpr(E->range(), SS, Prec_Decl-1);
SS << " = ";
self()->printSExpr(E->body(), SS, Prec_Decl);
}
- void printApply(Apply *E, StreamType &SS, bool sugared = false) {
- SExpr *F = E->fun();
+ void printApply(const Apply *E, StreamType &SS, bool sugared = false) {
+ const SExpr *F = E->fun();
if (F->opcode() == COP_Apply) {
printApply(cast<Apply>(F), SS, true);
SS << ", ";
@@ -763,7 +676,7 @@ protected:
SS << ")$";
}
- void printSApply(SApply *E, StreamType &SS) {
+ void printSApply(const SApply *E, StreamType &SS) {
self()->printSExpr(E->sfun(), SS, Prec_Postfix);
if (E->isDelegation()) {
SS << "@(";
@@ -772,14 +685,36 @@ protected:
}
}
- void printProject(Project *E, StreamType &SS) {
+ void printProject(const Project *E, StreamType &SS) {
+ if (CStyle) {
+ // Omit the this->
+ if (const SApply *SAP = dyn_cast<SApply>(E->record())) {
+ if (const Variable *V = dyn_cast<Variable>(SAP->sfun())) {
+ if (!SAP->isDelegation() && V->kind() == Variable::VK_SFun) {
+ SS << E->slotName();
+ return;
+ }
+ }
+ }
+ if (isa<Wildcard>(E->record())) {
+ // handle existentials
+ SS << "&";
+ SS << E->clangDecl()->getQualifiedNameAsString();
+ return;
+ }
+ }
self()->printSExpr(E->record(), SS, Prec_Postfix);
- SS << ".";
+ if (CStyle && E->isArrow()) {
+ SS << "->";
+ }
+ else {
+ SS << ".";
+ }
SS << E->slotName();
}
- void printCall(Call *E, StreamType &SS) {
- SExpr *T = E->target();
+ void printCall(const Call *E, StreamType &SS) {
+ const SExpr *T = E->target();
if (T->opcode() == COP_Apply) {
self()->printApply(cast<Apply>(T), SS, true);
SS << ")";
@@ -790,52 +725,60 @@ protected:
}
}
- void printAlloc(Alloc *E, StreamType &SS) {
+ void printAlloc(const Alloc *E, StreamType &SS) {
SS << "new ";
self()->printSExpr(E->dataType(), SS, Prec_Other-1);
}
- void printLoad(Load *E, StreamType &SS) {
+ void printLoad(const Load *E, StreamType &SS) {
self()->printSExpr(E->pointer(), SS, Prec_Postfix);
- SS << "^";
+ if (!CStyle)
+ SS << "^";
}
- void printStore(Store *E, StreamType &SS) {
+ void printStore(const Store *E, StreamType &SS) {
self()->printSExpr(E->destination(), SS, Prec_Other-1);
SS << " := ";
self()->printSExpr(E->source(), SS, Prec_Other-1);
}
- void printArrayIndex(ArrayIndex *E, StreamType &SS) {
+ void printArrayIndex(const ArrayIndex *E, StreamType &SS) {
self()->printSExpr(E->array(), SS, Prec_Postfix);
SS << "[";
self()->printSExpr(E->index(), SS, Prec_MAX);
SS << "]";
}
- void printArrayAdd(ArrayAdd *E, StreamType &SS) {
+ void printArrayAdd(const ArrayAdd *E, StreamType &SS) {
self()->printSExpr(E->array(), SS, Prec_Postfix);
SS << " + ";
self()->printSExpr(E->index(), SS, Prec_Atom);
}
- void printUnaryOp(UnaryOp *E, StreamType &SS) {
+ void printUnaryOp(const UnaryOp *E, StreamType &SS) {
SS << getUnaryOpcodeString(E->unaryOpcode());
self()->printSExpr(E->expr(), SS, Prec_Unary);
}
- void printBinaryOp(BinaryOp *E, StreamType &SS) {
+ void printBinaryOp(const BinaryOp *E, StreamType &SS) {
self()->printSExpr(E->expr0(), SS, Prec_Binary-1);
SS << " " << getBinaryOpcodeString(E->binaryOpcode()) << " ";
self()->printSExpr(E->expr1(), SS, Prec_Binary-1);
}
- void printCast(Cast *E, StreamType &SS) {
- SS << "%";
+ void printCast(const Cast *E, StreamType &SS) {
+ if (!CStyle) {
+ SS << "cast[";
+ SS << E->castOpcode();
+ SS << "](";
+ self()->printSExpr(E->expr(), SS, Prec_Unary);
+ SS << ")";
+ return;
+ }
self()->printSExpr(E->expr(), SS, Prec_Unary);
}
- void printSCFG(SCFG *E, StreamType &SS) {
+ void printSCFG(const SCFG *E, StreamType &SS) {
SS << "CFG {\n";
for (auto BBI : *E) {
printBasicBlock(BBI, SS);
@@ -844,39 +787,45 @@ protected:
newline(SS);
}
- void printBasicBlock(BasicBlock *E, StreamType &SS) {
+
+ void printBBInstr(const SExpr *E, StreamType &SS) {
+ bool Sub = false;
+ if (E->opcode() == COP_Variable) {
+ auto *V = cast<Variable>(E);
+ SS << "let " << V->name() << V->id() << " = ";
+ E = V->definition();
+ Sub = true;
+ }
+ else if (E->opcode() != COP_Store) {
+ SS << "let _x" << E->id() << " = ";
+ }
+ self()->printSExpr(E, SS, Prec_MAX, Sub);
+ SS << ";";
+ newline(SS);
+ }
+
+ void printBasicBlock(const BasicBlock *E, StreamType &SS) {
SS << "BB_" << E->blockID() << ":";
if (E->parent())
SS << " BB_" << E->parent()->blockID();
newline(SS);
- for (auto *A : E->arguments()) {
- 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();
+
+ for (auto *A : E->arguments())
+ printBBInstr(A, SS);
+
+ for (auto *I : E->instructions())
+ printBBInstr(I, SS);
+
+ const SExpr *T = E->terminator();
if (T) {
- self()->printSExpr(T, SS, Prec_MAX);
+ self()->printSExpr(T, SS, Prec_MAX, false);
SS << ";";
newline(SS);
}
newline(SS);
}
- void printPhi(Phi *E, StreamType &SS) {
+ void printPhi(const Phi *E, StreamType &SS) {
SS << "phi(";
if (E->status() == Phi::PH_SingleVal)
self()->printSExpr(E->values()[0], SS, Prec_MAX);
@@ -891,25 +840,38 @@ protected:
SS << ")";
}
- void printGoto(Goto *E, StreamType &SS) {
+ void printGoto(const Goto *E, StreamType &SS) {
SS << "goto ";
printBlockLabel(SS, E->targetBlock(), E->index());
}
- void printBranch(Branch *E, StreamType &SS) {
+ void printBranch(const Branch *E, StreamType &SS) {
SS << "branch (";
self()->printSExpr(E->condition(), SS, Prec_MAX);
SS << ") ";
- printBlockLabel(SS, E->thenBlock(), E->thenIndex());
+ printBlockLabel(SS, E->thenBlock(), -1);
SS << " ";
- printBlockLabel(SS, E->elseBlock(), E->elseIndex());
+ printBlockLabel(SS, E->elseBlock(), -1);
}
- void printIdentifier(Identifier *E, StreamType &SS) {
+ void printReturn(const Return *E, StreamType &SS) {
+ SS << "return ";
+ self()->printSExpr(E->returnValue(), SS, Prec_Other);
+ }
+
+ void printIdentifier(const Identifier *E, StreamType &SS) {
SS << E->name();
}
- void printIfThenElse(IfThenElse *E, StreamType &SS) {
+ void printIfThenElse(const IfThenElse *E, StreamType &SS) {
+ if (CStyle) {
+ printSExpr(E->condition(), SS, Prec_Unary);
+ SS << " ? ";
+ printSExpr(E->thenExpr(), SS, Prec_Unary);
+ SS << " : ";
+ printSExpr(E->elseExpr(), SS, Prec_Unary);
+ return;
+ }
SS << "if (";
printSExpr(E->condition(), SS, Prec_MAX);
SS << ") then ";
@@ -918,7 +880,7 @@ protected:
printSExpr(E->elseExpr(), SS, Prec_Other);
}
- void printLet(Let *E, StreamType &SS) {
+ void printLet(const Let *E, StreamType &SS) {
SS << "let ";
printVariable(E->variableDecl(), SS, true);
SS << " = ";
@@ -929,6 +891,10 @@ protected:
};
+class StdPrinter : public PrettyPrinter<StdPrinter, std::ostream> { };
+
+
+
} // end namespace til
} // end namespace threadSafety
} // end namespace clang
diff --git a/include/clang/Analysis/Analyses/ThreadSafetyUtil.h b/include/clang/Analysis/Analyses/ThreadSafetyUtil.h
index 31200a3a7253..ba3e0e519b09 100644
--- a/include/clang/Analysis/Analyses/ThreadSafetyUtil.h
+++ b/include/clang/Analysis/Analyses/ThreadSafetyUtil.h
@@ -11,19 +11,19 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_THREAD_SAFETY_UTIL_H
-#define LLVM_CLANG_THREAD_SAFETY_UTIL_H
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYUTIL_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYUTIL_H
+#include "clang/AST/ExprCXX.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/AlignOf.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Compiler.h"
-#include "clang/AST/ExprCXX.h"
-
#include <cassert>
#include <cstddef>
-#include <vector>
+#include <ostream>
#include <utility>
+#include <vector>
namespace clang {
namespace threadSafety {
@@ -142,18 +142,35 @@ public:
assert(i < Size && "Array index out of bounds.");
return Data[i];
}
+ T &back() {
+ assert(Size && "No elements in the array.");
+ return Data[Size - 1];
+ }
+ const T &back() const {
+ assert(Size && "No elements in the array.");
+ return Data[Size - 1];
+ }
iterator begin() { return Data; }
- iterator end() { return Data + Size; }
+ iterator end() { return Data + Size; }
+
+ const_iterator begin() const { return Data; }
+ const_iterator end() const { return Data + Size; }
const_iterator cbegin() const { return Data; }
- const_iterator cend() const { return Data + Size; }
+ const_iterator cend() const { return Data + Size; }
void push_back(const T &Elem) {
assert(Size < Capacity);
Data[Size++] = Elem;
}
+ // drop last n elements from array
+ void drop(unsigned n = 0) {
+ assert(Size > n);
+ Size -= n;
+ }
+
void setValues(unsigned Sz, const T& C) {
assert(Sz <= Capacity);
Size = Sz;
@@ -171,6 +188,37 @@ public:
return J - Osz;
}
+ // An adaptor to reverse a simple array
+ class ReverseAdaptor {
+ public:
+ ReverseAdaptor(SimpleArray &Array) : Array(Array) {}
+ // A reverse iterator used by the reverse adaptor
+ class Iterator {
+ public:
+ Iterator(T *Data) : Data(Data) {}
+ T &operator*() { return *Data; }
+ const T &operator*() const { return *Data; }
+ Iterator &operator++() {
+ --Data;
+ return *this;
+ }
+ bool operator!=(Iterator Other) { return Data != Other.Data; }
+
+ private:
+ T *Data;
+ };
+ Iterator begin() { return Array.end() - 1; }
+ Iterator end() { return Array.begin() - 1; }
+ const Iterator begin() const { return Array.end() - 1; }
+ const Iterator end() const { return Array.begin() - 1; }
+
+ private:
+ SimpleArray &Array;
+ };
+
+ const ReverseAdaptor reverse() const { return ReverseAdaptor(*this); }
+ ReverseAdaptor reverse() { return ReverseAdaptor(*this); }
+
private:
// std::max is annoying here, because it requires a reference,
// thus forcing InitialCapacity to be initialized outside the .h file.
@@ -185,6 +233,7 @@ private:
size_t Capacity;
};
+
} // end namespace til
@@ -310,6 +359,11 @@ private:
};
+inline std::ostream& operator<<(std::ostream& ss, const StringRef str) {
+ return ss.write(str.data(), str.size());
+}
+
+
} // end namespace threadSafety
} // end namespace clang
diff --git a/include/clang/Analysis/Analyses/UninitializedValues.h b/include/clang/Analysis/Analyses/UninitializedValues.h
index 188722d94b3a..53ff20c23560 100644
--- a/include/clang/Analysis/Analyses/UninitializedValues.h
+++ b/include/clang/Analysis/Analyses/UninitializedValues.h
@@ -12,8 +12,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_UNINIT_VALS_H
-#define LLVM_CLANG_UNINIT_VALS_H
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_UNINITIALIZEDVALUES_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_UNINITIALIZEDVALUES_H
#include "clang/AST/Stmt.h"
#include "llvm/ADT/SmallVector.h"
diff --git a/include/clang/Analysis/AnalysisContext.h b/include/clang/Analysis/AnalysisContext.h
index 08e335418ab7..0ebdf15f2c4e 100644
--- a/include/clang/Analysis/AnalysisContext.h
+++ b/include/clang/Analysis/AnalysisContext.h
@@ -17,6 +17,7 @@
#include "clang/AST/Decl.h"
#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/CodeInjector.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/Support/Allocator.h"
@@ -143,6 +144,14 @@ public:
/// \sa getBody
bool isBodyAutosynthesized() const;
+ /// \brief Checks if the body of the Decl is generated by the BodyFarm from a
+ /// model file.
+ ///
+ /// Note, the lookup is not free. We are going to call getBody behind
+ /// the scenes.
+ /// \sa getBody
+ bool isBodyAutosynthesizedFromModelFile() const;
+
CFG *getCFG();
CFGStmtMap *getCFGStmtMap();
@@ -398,6 +407,10 @@ class AnalysisDeclContextManager {
ContextMap Contexts;
LocationContextManager LocContexts;
CFG::BuildOptions cfgBuildOptions;
+
+ /// Pointer to an interface that can provide function bodies for
+ /// declarations from external source.
+ std::unique_ptr<CodeInjector> Injector;
/// Flag to indicate whether or not bodies should be synthesized
/// for well-known functions.
@@ -410,7 +423,8 @@ public:
bool addTemporaryDtors = false,
bool synthesizeBodies = false,
bool addStaticInitBranches = false,
- bool addCXXNewAllocator = true);
+ bool addCXXNewAllocator = true,
+ CodeInjector* injector = nullptr);
~AnalysisDeclContextManager();
diff --git a/include/clang/Analysis/AnalysisDiagnostic.h b/include/clang/Analysis/AnalysisDiagnostic.h
index 33c940e7bbf0..8d28971cfe5c 100644
--- a/include/clang/Analysis/AnalysisDiagnostic.h
+++ b/include/clang/Analysis/AnalysisDiagnostic.h
@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_DIAGNOSTICANALYSIS_H
-#define LLVM_CLANG_DIAGNOSTICANALYSIS_H
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSISDIAGNOSTIC_H
+#define LLVM_CLANG_ANALYSIS_ANALYSISDIAGNOSTIC_H
#include "clang/Basic/Diagnostic.h"
diff --git a/include/clang/Analysis/CFG.h b/include/clang/Analysis/CFG.h
index 891fb90691f3..beea867228d6 100644
--- a/include/clang/Analysis/CFG.h
+++ b/include/clang/Analysis/CFG.h
@@ -12,8 +12,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_CFG_H
-#define LLVM_CLANG_CFG_H
+#ifndef LLVM_CLANG_ANALYSIS_CFG_H
+#define LLVM_CLANG_ANALYSIS_CFG_H
#include "clang/AST/Stmt.h"
#include "clang/Analysis/Support/BumpVector.h"
@@ -811,10 +811,9 @@ public:
ImplTy I;
};
- /// buildCFG - Builds a CFG from an AST. The responsibility to free the
- /// constructed CFG belongs to the caller.
- static CFG* buildCFG(const Decl *D, Stmt *AST, ASTContext *C,
- const BuildOptions &BO);
+ /// buildCFG - Builds a CFG from an AST.
+ static std::unique_ptr<CFG> buildCFG(const Decl *D, Stmt *AST, ASTContext *C,
+ const BuildOptions &BO);
/// createBlock - Create a new block in the CFG. The CFG owns the block;
/// the caller should not directly free it.
diff --git a/include/clang/Analysis/CFGStmtMap.h b/include/clang/Analysis/CFGStmtMap.h
index 6e8e140afb23..4dfa91df0f42 100644
--- a/include/clang/Analysis/CFGStmtMap.h
+++ b/include/clang/Analysis/CFGStmtMap.h
@@ -12,8 +12,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_CFGSTMTMAP_H
-#define LLVM_CLANG_CFGSTMTMAP_H
+#ifndef LLVM_CLANG_ANALYSIS_CFGSTMTMAP_H
+#define LLVM_CLANG_ANALYSIS_CFGSTMTMAP_H
#include "clang/Analysis/CFG.h"
diff --git a/include/clang/Analysis/CallGraph.h b/include/clang/Analysis/CallGraph.h
index 593ba575c78e..eda22a57e8a5 100644
--- a/include/clang/Analysis/CallGraph.h
+++ b/include/clang/Analysis/CallGraph.h
@@ -14,8 +14,8 @@
// edges to all externally available functions.
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_ANALYSIS_CALLGRAPH
-#define LLVM_CLANG_ANALYSIS_CALLGRAPH
+#ifndef LLVM_CLANG_ANALYSIS_CALLGRAPH_H
+#define LLVM_CLANG_ANALYSIS_CALLGRAPH_H
#include "clang/AST/DeclBase.h"
#include "clang/AST/RecursiveASTVisitor.h"
diff --git a/include/clang/Analysis/CodeInjector.h b/include/clang/Analysis/CodeInjector.h
new file mode 100644
index 000000000000..413a55b05b07
--- /dev/null
+++ b/include/clang/Analysis/CodeInjector.h
@@ -0,0 +1,46 @@
+//===-- CodeInjector.h ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines the clang::CodeInjector interface which is responsible for
+/// injecting AST of function definitions that may not be available in the
+/// original source.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_CODEINJECTOR_H
+#define LLVM_CLANG_ANALYSIS_CODEINJECTOR_H
+
+namespace clang {
+
+class Stmt;
+class FunctionDecl;
+class ObjCMethodDecl;
+
+/// \brief CodeInjector is an interface which is responsible for injecting AST
+/// of function definitions that may not be available in the original source.
+///
+/// The getBody function will be called each time the static analyzer examines a
+/// function call that has no definition available in the current translation
+/// unit. If the returned statement is not a null pointer, it is assumed to be
+/// the body of a function which will be used for the analysis. The source of
+/// the body can be arbitrary, but it is advised to use memoization to avoid
+/// unnecessary reparsing of the external source that provides the body of the
+/// functions.
+class CodeInjector {
+public:
+ CodeInjector();
+ virtual ~CodeInjector();
+
+ virtual Stmt *getBody(const FunctionDecl *D) = 0;
+ virtual Stmt *getBody(const ObjCMethodDecl *D) = 0;
+};
+}
+
+#endif
diff --git a/include/clang/Analysis/DomainSpecific/CocoaConventions.h b/include/clang/Analysis/DomainSpecific/CocoaConventions.h
index e6a2f13a0b80..8b3fcff52d08 100644
--- a/include/clang/Analysis/DomainSpecific/CocoaConventions.h
+++ b/include/clang/Analysis/DomainSpecific/CocoaConventions.h
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_ANALYSIS_DS_COCOA
-#define LLVM_CLANG_ANALYSIS_DS_COCOA
+#ifndef LLVM_CLANG_ANALYSIS_DOMAINSPECIFIC_COCOACONVENTIONS_H
+#define LLVM_CLANG_ANALYSIS_DOMAINSPECIFIC_COCOACONVENTIONS_H
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/StringRef.h"
diff --git a/include/clang/Analysis/DomainSpecific/ObjCNoReturn.h b/include/clang/Analysis/DomainSpecific/ObjCNoReturn.h
index 930c2bd0925b..f9e800a4a412 100644
--- a/include/clang/Analysis/DomainSpecific/ObjCNoReturn.h
+++ b/include/clang/Analysis/DomainSpecific/ObjCNoReturn.h
@@ -12,8 +12,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_ANALYSIS_DS_OBJCNORETURN
-#define LLVM_CLANG_ANALYSIS_DS_OBJCNORETURN
+#ifndef LLVM_CLANG_ANALYSIS_DOMAINSPECIFIC_OBJCNORETURN_H
+#define LLVM_CLANG_ANALYSIS_DOMAINSPECIFIC_OBJCNORETURN_H
#include "clang/Basic/IdentifierTable.h"
diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h
index 57324d042908..f87271550c20 100644
--- a/include/clang/Analysis/ProgramPoint.h
+++ b/include/clang/Analysis/ProgramPoint.h
@@ -12,8 +12,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_ANALYSIS_PROGRAM_POINT
-#define LLVM_CLANG_ANALYSIS_PROGRAM_POINT
+#ifndef LLVM_CLANG_ANALYSIS_PROGRAMPOINT_H
+#define LLVM_CLANG_ANALYSIS_PROGRAMPOINT_H
#include "clang/Analysis/AnalysisContext.h"
#include "clang/Analysis/CFG.h"
diff --git a/include/clang/Analysis/Support/BumpVector.h b/include/clang/Analysis/Support/BumpVector.h
index 6d0427ba92b5..841adf64557d 100644
--- a/include/clang/Analysis/Support/BumpVector.h
+++ b/include/clang/Analysis/Support/BumpVector.h
@@ -16,8 +16,8 @@
// refactor this core logic into something common that is shared between
// the two. The main thing that is different is the allocation strategy.
-#ifndef LLVM_CLANG_BUMP_VECTOR
-#define LLVM_CLANG_BUMP_VECTOR
+#ifndef LLVM_CLANG_ANALYSIS_SUPPORT_BUMPVECTOR_H
+#define LLVM_CLANG_ANALYSIS_SUPPORT_BUMPVECTOR_H
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/Support/Allocator.h"
@@ -241,4 +241,4 @@ void BumpVector<T>::grow(BumpVectorContext &C, size_t MinSize) {
}
} // end: clang namespace
-#endif // end: LLVM_CLANG_BUMP_VECTOR
+#endif
diff --git a/include/clang/Basic/ABI.h b/include/clang/Basic/ABI.h
index 9e8ef2e3ee8e..bd246792fe24 100644
--- a/include/clang/Basic/ABI.h
+++ b/include/clang/Basic/ABI.h
@@ -13,8 +13,8 @@
///
//===----------------------------------------------------------------------===//
-#ifndef CLANG_BASIC_ABI_H
-#define CLANG_BASIC_ABI_H
+#ifndef LLVM_CLANG_BASIC_ABI_H
+#define LLVM_CLANG_BASIC_ABI_H
#include "llvm/Support/DataTypes.h"
@@ -24,14 +24,15 @@ namespace clang {
enum CXXCtorType {
Ctor_Complete, ///< Complete object ctor
Ctor_Base, ///< Base object ctor
- Ctor_CompleteAllocating ///< Complete object allocating ctor
+ Ctor_Comdat ///< The COMDAT used for ctors
};
/// \brief C++ destructor types.
enum CXXDtorType {
Dtor_Deleting, ///< Deleting dtor
Dtor_Complete, ///< Complete object dtor
- Dtor_Base ///< Base object dtor
+ Dtor_Base, ///< Base object dtor
+ Dtor_Comdat ///< The COMDAT used for dtors
};
/// \brief A return adjustment.
@@ -204,4 +205,4 @@ struct ThunkInfo {
} // end namespace clang
-#endif // CLANG_BASIC_ABI_H
+#endif
diff --git a/include/clang/Basic/AddressSpaces.h b/include/clang/Basic/AddressSpaces.h
index 4b1cea50f884..8dd75660c672 100644
--- a/include/clang/Basic/AddressSpaces.h
+++ b/include/clang/Basic/AddressSpaces.h
@@ -30,6 +30,7 @@ enum ID {
opencl_global = Offset,
opencl_local,
opencl_constant,
+ opencl_generic,
cuda_device,
cuda_constant,
diff --git a/include/clang/Basic/AllDiagnostics.h b/include/clang/Basic/AllDiagnostics.h
index 7304c8f673e6..18a2b8a31871 100644
--- a/include/clang/Basic/AllDiagnostics.h
+++ b/include/clang/Basic/AllDiagnostics.h
@@ -12,8 +12,8 @@
///
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_ALL_DIAGNOSTICS_H
-#define LLVM_CLANG_ALL_DIAGNOSTICS_H
+#ifndef LLVM_CLANG_BASIC_ALLDIAGNOSTICS_H
+#define LLVM_CLANG_BASIC_ALLDIAGNOSTICS_H
#include "clang/AST/ASTDiagnostic.h"
#include "clang/AST/CommentDiagnostic.h"
diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td
index 704a375ba291..843746111463 100644
--- a/include/clang/Basic/Attr.td
+++ b/include/clang/Basic/Attr.td
@@ -115,6 +115,10 @@ def DeclBase : AttrSubject;
def FunctionLike : SubsetSubject<DeclBase,
[{S->getFunctionType(false) != NULL}]>;
+def OpenCLKernelFunction : SubsetSubject<Function, [{
+ S->hasAttr<OpenCLKernelAttr>()
+}]>;
+
// HasFunctionProto is a more strict version of FunctionLike, so it should
// never be specified in a Subjects list along with FunctionLike (due to the
// inclusive nature of subject testing).
@@ -186,10 +190,11 @@ class Spelling<string name, string variety> {
class GNU<string name> : Spelling<name, "GNU">;
class Declspec<string name> : Spelling<name, "Declspec">;
-class CXX11<string namespace, string name> : Spelling<name, "CXX11"> {
+class CXX11<string namespace, string name, int version = 1>
+ : Spelling<name, "CXX11"> {
string Namespace = namespace;
-}
-class Keyword<string name> : Spelling<name, "Keyword">;
+ int Version = version;
+} class Keyword<string name> : Spelling<name, "Keyword">;
class Pragma<string namespace, string name> : Spelling<name, "Pragma"> {
string Namespace = namespace;
}
@@ -219,12 +224,14 @@ class SubjectList<list<AttrSubject> subjects, SubjectDiag diag = WarnDiag,
string CustomDiag = customDiag;
}
-class LangOpt<string name> {
+class LangOpt<string name, bit negated = 0> {
string Name = name;
+ bit Negated = negated;
}
def MicrosoftExt : LangOpt<"MicrosoftExt">;
def Borland : LangOpt<"Borland">;
def CUDA : LangOpt<"CUDA">;
+def COnly : LangOpt<"CPlusPlus", 1>;
// Defines targets for target-specific attributes. The list of strings should
// specify architectures for which the target applies, based off the ArchType
@@ -354,6 +361,24 @@ def Aligned : InheritableAttr {
let Documentation = [Undocumented];
}
+def AlignValue : Attr {
+ let Spellings = [
+ // Unfortunately, this is semantically an assertion, not a directive
+ // (something else must ensure the alignment), so aligned_value is a
+ // probably a better name. We might want to add an aligned_value spelling in
+ // the future (and a corresponding C++ attribute), but this can be done
+ // later once we decide if we also want them to have slightly-different
+ // semantics than Intel's align_value.
+ GNU<"align_value">
+ // Intel's compiler on Windows also supports:
+ // , Declspec<"align_value">
+ ];
+ let Args = [ExprArgument<"Alignment">];
+ let Subjects = SubjectList<[Var, TypedefName], WarnDiag,
+ "ExpectedVariableOrTypedef">;
+ let Documentation = [AlignValueDocs];
+}
+
def AlignMac68k : InheritableAttr {
// This attribute has no spellings as it is only ever created implicitly.
let Spellings = [];
@@ -434,7 +459,8 @@ def Bounded : IgnoredAttr {
}
def CarriesDependency : InheritableParamAttr {
- let Spellings = [GNU<"carries_dependency">, CXX11<"","carries_dependency">];
+ let Spellings = [GNU<"carries_dependency">,
+ CXX11<"","carries_dependency", 200809>];
let Subjects = SubjectList<[ParmVar, ObjCMethod, Function], ErrorDiag>;
let Documentation = [CarriesDependencyDocs];
}
@@ -541,6 +567,13 @@ def CUDAHost : InheritableAttr {
let Documentation = [Undocumented];
}
+def CUDAInvalidTarget : InheritableAttr {
+ let Spellings = [];
+ let Subjects = SubjectList<[Function]>;
+ let LangOpts = [CUDA];
+ let Documentation = [Undocumented];
+}
+
def CUDALaunchBounds : InheritableAttr {
let Spellings = [GNU<"launch_bounds">];
let Args = [IntArgument<"MaxThreads">, DefaultIntArgument<"MinBlocks", 0>];
@@ -568,7 +601,7 @@ def C11NoReturn : InheritableAttr {
}
def CXX11NoReturn : InheritableAttr {
- let Spellings = [CXX11<"","noreturn">];
+ let Spellings = [CXX11<"","noreturn", 200809>];
let Subjects = SubjectList<[Function], ErrorDiag>;
let Documentation = [CXX11NoReturnDocs];
}
@@ -597,27 +630,32 @@ def OpenCLImageAccess : Attr {
def OpenCLPrivateAddressSpace : TypeAttr {
let Spellings = [Keyword<"__private">, Keyword<"private">];
- let Documentation = [Undocumented];
+ let Documentation = [OpenCLAddressSpacePrivateDocs];
}
def OpenCLGlobalAddressSpace : TypeAttr {
let Spellings = [Keyword<"__global">, Keyword<"global">];
- let Documentation = [Undocumented];
+ let Documentation = [OpenCLAddressSpaceGlobalDocs];
}
def OpenCLLocalAddressSpace : TypeAttr {
let Spellings = [Keyword<"__local">, Keyword<"local">];
- let Documentation = [Undocumented];
+ let Documentation = [OpenCLAddressSpaceLocalDocs];
}
def OpenCLConstantAddressSpace : TypeAttr {
let Spellings = [Keyword<"__constant">, Keyword<"constant">];
- let Documentation = [Undocumented];
+ let Documentation = [OpenCLAddressSpaceConstantDocs];
+}
+
+def OpenCLGenericAddressSpace : TypeAttr {
+ let Spellings = [Keyword<"__generic">, Keyword<"generic">];
+ let Documentation = [OpenCLAddressSpaceGenericDocs];
}
def Deprecated : InheritableAttr {
let Spellings = [GCC<"deprecated">, Declspec<"deprecated">,
- CXX11<"","deprecated">];
+ CXX11<"","deprecated", 201309>];
let Args = [StringArgument<"Message", 1>];
let Documentation = [Undocumented];
}
@@ -655,7 +693,7 @@ def FastCall : InheritableAttr {
let Spellings = [GCC<"fastcall">, Keyword<"__fastcall">,
Keyword<"_fastcall">];
// let Subjects = [Function, ObjCMethod];
- let Documentation = [Undocumented];
+ let Documentation = [FastCallDocs];
}
def Final : InheritableAttr {
@@ -671,6 +709,25 @@ def MinSize : InheritableAttr {
let Documentation = [Undocumented];
}
+def FlagEnum : InheritableAttr {
+ let Spellings = [GNU<"flag_enum">];
+ let Subjects = SubjectList<[Enum]>;
+ let Documentation = [FlagEnumDocs];
+ let LangOpts = [COnly];
+ let AdditionalMembers = [{
+private:
+ llvm::APInt FlagBits;
+public:
+ llvm::APInt &getFlagBits() {
+ return FlagBits;
+ }
+
+ const llvm::APInt &getFlagBits() const {
+ return FlagBits;
+ }
+}];
+}
+
def Flatten : InheritableAttr {
let Spellings = [GCC<"flatten">];
let Subjects = SubjectList<[Function], ErrorDiag>;
@@ -754,7 +811,7 @@ def MayAlias : InheritableAttr {
def MSABI : InheritableAttr {
let Spellings = [GCC<"ms_abi">];
// let Subjects = [Function, ObjCMethod];
- let Documentation = [Undocumented];
+ let Documentation = [MSABIDocs];
}
def MSP430Interrupt : InheritableAttr, TargetSpecificAttr<TargetMSP430> {
@@ -810,7 +867,7 @@ def NoCommon : InheritableAttr {
}
def NoDebug : InheritableAttr {
- let Spellings = [GNU<"nodebug">];
+ let Spellings = [GCC<"nodebug">];
let Documentation = [Undocumented];
}
@@ -832,6 +889,38 @@ def NoMips16 : InheritableAttr, TargetSpecificAttr<TargetMips> {
let Documentation = [Undocumented];
}
+// This is not a TargetSpecificAttr so that is silently accepted and
+// ignored on other targets as encouraged by the OpenCL spec.
+//
+// See OpenCL 1.2 6.11.5: "It is our intention that a particular
+// implementation of OpenCL be free to ignore all attributes and the
+// resulting executable binary will produce the same result."
+//
+// However, only AMD GPU targets will emit the corresponding IR
+// attribute.
+//
+// FIXME: This provides a sub-optimal error message if you attempt to
+// use this in CUDA, since CUDA does not use the same terminology.
+def AMDGPUNumVGPR : InheritableAttr {
+ let Spellings = [GNU<"amdgpu_num_vgpr">];
+ let Args = [UnsignedArgument<"NumVGPR">];
+ let Documentation = [AMDGPUNumVGPRDocs];
+
+// FIXME: This should be for OpenCLKernelFunction, but is not to
+// workaround needing to see kernel attribute before others to know if
+// this should be rejected on non-kernels.
+ let Subjects = SubjectList<[Function], ErrorDiag,
+ "ExpectedKernelFunction">;
+}
+
+def AMDGPUNumSGPR : InheritableAttr {
+ let Spellings = [GNU<"amdgpu_num_sgpr">];
+ let Args = [UnsignedArgument<"NumSGPR">];
+ let Documentation = [AMDGPUNumSGPRDocs];
+ let Subjects = SubjectList<[Function], ErrorDiag,
+ "ExpectedKernelFunction">;
+}
+
def NoSplitStack : InheritableAttr {
let Spellings = [GCC<"no_split_stack">];
let Subjects = SubjectList<[Function], ErrorDiag>;
@@ -845,11 +934,15 @@ def NonNull : InheritableAttr {
let Args = [VariadicUnsignedArgument<"Args">];
let AdditionalMembers =
[{bool isNonNull(unsigned idx) const {
+ if (!args_size())
+ return true;
for (const auto &V : args())
if (V == idx)
return true;
return false;
} }];
+ // FIXME: We should merge duplicates into a single nonnull attribute.
+ let DuplicatesAllowedWhileMerging = 1;
let Documentation = [Undocumented];
}
@@ -860,6 +953,13 @@ def ReturnsNonNull : InheritableAttr {
let Documentation = [Undocumented];
}
+def AssumeAligned : InheritableAttr {
+ let Spellings = [GCC<"assume_aligned">];
+ let Subjects = SubjectList<[ObjCMethod, Function]>;
+ let Args = [ExprArgument<"Alignment">, ExprArgument<"Offset", 1>];
+ let Documentation = [AssumeAlignedDocs];
+}
+
def NoReturn : InheritableAttr {
let Spellings = [GCC<"noreturn">, Declspec<"noreturn">];
// FIXME: Does GCC allow this on the function instead?
@@ -1068,7 +1168,7 @@ def Pure : InheritableAttr {
def Regparm : TypeAttr {
let Spellings = [GCC<"regparm">];
let Args = [UnsignedArgument<"NumParams">];
- let Documentation = [Undocumented];
+ let Documentation = [RegparmDocs];
}
def ReqdWorkGroupSize : InheritableAttr {
@@ -1115,7 +1215,7 @@ def Sentinel : InheritableAttr {
def StdCall : InheritableAttr {
let Spellings = [GCC<"stdcall">, Keyword<"__stdcall">, Keyword<"_stdcall">];
// let Subjects = [Function, ObjCMethod];
- let Documentation = [Undocumented];
+ let Documentation = [StdCallDocs];
}
def SysVABI : InheritableAttr {
@@ -1128,7 +1228,14 @@ def ThisCall : InheritableAttr {
let Spellings = [GCC<"thiscall">, Keyword<"__thiscall">,
Keyword<"_thiscall">];
// let Subjects = [Function, ObjCMethod];
- let Documentation = [Undocumented];
+ let Documentation = [ThisCallDocs];
+}
+
+def VectorCall : InheritableAttr {
+ let Spellings = [GNU<"vectorcall">, Keyword<"__vectorcall">,
+ Keyword<"_vectorcall">];
+// let Subjects = [Function, ObjCMethod];
+ let Documentation = [VectorCallDocs];
}
def Pascal : InheritableAttr {
@@ -1784,14 +1891,21 @@ def Unaligned : IgnoredAttr {
}
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">];
+ /// #pragma clang loop <option> directive
+ /// vectorize: vectorizes loop operations if State == Enable.
+ /// vectorize_width: vectorize loop operations with width 'Value'.
+ /// interleave: interleave multiple loop iterations if State == Enable.
+ /// interleave_count: interleaves 'Value' loop interations.
+ /// unroll: fully unroll loop if State == Enable.
+ /// unroll_count: unrolls loop 'Value' times.
+
+ /// #pragma unroll <argument> directive
+ /// <no arg>: fully unrolls loop.
+ /// boolean: fully unrolls loop if State == Enable.
+ /// expression: unrolls loop 'Value' times.
+
+ let Spellings = [Pragma<"clang", "loop">, Pragma<"", "unroll">,
+ Pragma<"", "nounroll">];
/// State of the loop optimization specified by the spelling.
let Args = [EnumArgument<"Option", "OptionType",
@@ -1799,10 +1913,13 @@ def LoopHint : Attr {
"unroll", "unroll_count"],
["Vectorize", "VectorizeWidth", "Interleave", "InterleaveCount",
"Unroll", "UnrollCount"]>,
- DefaultIntArgument<"Value", 1>];
+ EnumArgument<"State", "LoopHintState",
+ ["default", "enable", "disable"],
+ ["Default", "Enable", "Disable"]>,
+ ExprArgument<"Value">];
let AdditionalMembers = [{
- static StringRef getOptionName(int Option) {
+ static const char *getOptionName(int Option) {
switch(Option) {
case Vectorize: return "vectorize";
case VectorizeWidth: return "vectorize_width";
@@ -1814,59 +1931,68 @@ def LoopHint : Attr {
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);
+ // For "#pragma unroll" and "#pragma nounroll" the string "unroll" or
+ // "nounroll" is already emitted as the pragma name.
+ if (SpellingIndex == Pragma_nounroll) {
OS << "\n";
return;
}
+ else if (SpellingIndex == Pragma_unroll) {
+ OS << getValueString(Policy) << "\n";
+ return;
+ }
+
assert(SpellingIndex == Pragma_clang_loop && "Unexpected spelling");
- OS << getOptionName(option);
- printArgument(OS);
- OS << "\n";
+ OS << getOptionName(option) << getValueString(Policy) << "\n";
}
- // Prints the loop hint argument including the enclosing parentheses to OS.
- void printArgument(raw_ostream &OS) const {
+ // Return a string containing the loop hint argument including the
+ // enclosing parentheses.
+ std::string getValueString(const PrintingPolicy &Policy) const {
+ std::string ValueName;
+ llvm::raw_string_ostream OS(ValueName);
OS << "(";
if (option == VectorizeWidth || option == InterleaveCount ||
option == UnrollCount)
- OS << value;
- else if (value)
- OS << "enable";
+ value->printPretty(OS, nullptr, Policy);
+ else if (state == Default)
+ return "";
+ else if (state == Enable)
+ OS << (option == Unroll ? "full" : "enable");
else
OS << "disable";
OS << ")";
+ return OS.str();
}
// Return a string suitable for identifying this attribute in diagnostics.
- std::string getDiagnosticName() const {
- std::string DiagnosticName;
- llvm::raw_string_ostream OS(DiagnosticName);
+ std::string getDiagnosticName(const PrintingPolicy &Policy) const {
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();
+ if (SpellingIndex == Pragma_nounroll)
+ return "#pragma nounroll";
+ else if (SpellingIndex == Pragma_unroll)
+ return "#pragma unroll" + getValueString(Policy);
+
+ assert(SpellingIndex == Pragma_clang_loop && "Unexpected spelling");
+ return getOptionName(option) + getValueString(Policy);
}
}];
let Documentation = [LoopHintDocs, UnrollHintDocs];
}
+
+def CapturedRecord : InheritableAttr {
+ // This attribute has no spellings as it is only ever created implicitly.
+ let Spellings = [];
+ let SemaHandler = 0;
+ let Documentation = [Undocumented];
+}
+
+def OMPThreadPrivateDecl : InheritableAttr {
+ // This attribute has no spellings as it is only ever created implicitly.
+ let Spellings = [];
+ let SemaHandler = 0;
+ let Documentation = [Undocumented];
+}
diff --git a/include/clang/Basic/AttrDocs.td b/include/clang/Basic/AttrDocs.td
index e6d6a33d3b5d..918abb6072ea 100644
--- a/include/clang/Basic/AttrDocs.td
+++ b/include/clang/Basic/AttrDocs.td
@@ -72,9 +72,9 @@ def ThreadDocs : Documentation {
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_.
+compatibility. See the documentation for `__declspec(thread)`_ on MSDN.
-.. _MSDN: http://msdn.microsoft.com/en-us/library/9w1sdazb.aspx
+.. _`__declspec(thread)`: http://msdn.microsoft.com/en-us/library/9w1sdazb.aspx
In Clang, ``__declspec(thread)`` is generally equivalent in functionality to the
GNU ``__thread`` keyword. The variable must not have a destructor and must have
@@ -154,6 +154,30 @@ def ReleaseCapabilityDocs : Documentation {
Marks a function as releasing a capability.
}];
}
+
+def AssumeAlignedDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+Use ``__attribute__((assume_aligned(<alignment>[,<offset>]))`` on a function
+declaration to specify that the return value of the function (which must be a
+pointer type) has the specified offset, in bytes, from an address with the
+specified alignment. The offset is taken to be zero if omitted.
+
+.. code-block:: c++
+
+ // The returned pointer value has 32-byte alignment.
+ void *a() __attribute__((assume_aligned (32)));
+
+ // The returned pointer value is 4 bytes greater than an address having
+ // 32-byte alignment.
+ void *b() __attribute__((assume_aligned (32, 4)));
+
+Note that this attribute provides information to the compiler regarding a
+condition that the code already ensures is true. It does not cause the compiler
+to enforce the provided alignment assumption.
+ }];
+}
+
def EnableIfDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
@@ -649,15 +673,180 @@ The semantics are as follows:
}];
}
+def DocCatAMDGPURegisterAttributes :
+ DocumentationCategory<"AMD GPU Register Attributes"> {
+ let Content = [{
+Clang supports attributes for controlling register usage on AMD GPU
+targets. These attributes may be attached to a kernel function
+definition and is an optimization hint to the backend for the maximum
+number of registers to use. This is useful in cases where register
+limited occupancy is known to be an important factor for the
+performance for the kernel.
+
+The semantics are as follows:
+
+- The backend will attempt to limit the number of used registers to
+ the specified value, but the exact number used is not
+ guaranteed. The number used may be rounded up to satisfy the
+ allocation requirements or ABI constraints of the subtarget. For
+ example, on Southern Islands VGPRs may only be allocated in
+ increments of 4, so requesting a limit of 39 VGPRs will really
+ attempt to use up to 40. Requesting more registers than the
+ subtarget supports will truncate to the maximum allowed. The backend
+ may also use fewer registers than requested whenever possible.
+
+- 0 implies the default no limit on register usage.
+
+- Ignored on older VLIW subtargets which did not have separate scalar
+ and vector registers, R600 through Northern Islands.
+
+}];
+}
+
+
+def AMDGPUNumVGPRDocs : Documentation {
+ let Category = DocCatAMDGPURegisterAttributes;
+ let Content = [{
+Clang supports the
+``__attribute__((amdgpu_num_vgpr(<num_registers>)))`` attribute on AMD
+Southern Islands GPUs and later for controlling the number of vector
+registers. A typical value would be between 4 and 256 in increments
+of 4.
+}];
+}
+
+def AMDGPUNumSGPRDocs : Documentation {
+ let Category = DocCatAMDGPURegisterAttributes;
+ let Content = [{
+
+Clang supports the
+``__attribute__((amdgpu_num_sgpr(<num_registers>)))`` attribute on AMD
+Southern Islands GPUs and later for controlling the number of scalar
+registers. A typical value would be between 8 and 104 in increments of
+8.
+
+Due to common instruction constraints, an additional 2-4 SGPRs are
+typically required for internal use depending on features used. This
+value is a hint for the total number of SGPRs to use, and not the
+number of user SGPRs, so no special consideration needs to be given
+for these.
+}];
+}
+
+def DocCatCallingConvs : DocumentationCategory<"Calling Conventions"> {
+ let Content = [{
+Clang supports several different calling conventions, depending on the target
+platform and architecture. The calling convention used for a function determines
+how parameters are passed, how results are returned to the caller, and other
+low-level details of calling a function.
+ }];
+}
+
def PcsDocs : Documentation {
- let Category = DocCatFunction;
+ let Category = DocCatCallingConvs;
let Content = [{
-On ARM targets, this can attribute can be used to select calling conventions,
+On ARM targets, this attribute can be used to select calling conventions
similar to ``stdcall`` on x86. Valid parameter values are "aapcs" and
"aapcs-vfp".
}];
}
+def RegparmDocs : Documentation {
+ let Category = DocCatCallingConvs;
+ let Content = [{
+On 32-bit x86 targets, the regparm attribute causes the compiler to pass
+the first three integer parameters in EAX, EDX, and ECX instead of on the
+stack. This attribute has no effect on variadic functions, and all parameters
+are passed via the stack as normal.
+ }];
+}
+
+def SysVABIDocs : Documentation {
+ let Category = DocCatCallingConvs;
+ let Content = [{
+On Windows x86_64 targets, this attribute changes the calling convention of a
+function to match the default convention used on Sys V targets such as Linux,
+Mac, and BSD. This attribute has no effect on other targets.
+ }];
+}
+
+def MSABIDocs : Documentation {
+ let Category = DocCatCallingConvs;
+ let Content = [{
+On non-Windows x86_64 targets, this attribute changes the calling convention of
+a function to match the default convention used on Windows x86_64. This
+attribute has no effect on Windows targets or non-x86_64 targets.
+ }];
+}
+
+def StdCallDocs : Documentation {
+ let Category = DocCatCallingConvs;
+ let Content = [{
+On 32-bit x86 targets, this attribute changes the calling convention of a
+function to clear parameters off of the stack on return. This convention does
+not support variadic calls or unprototyped functions in C, and has no effect on
+x86_64 targets. This calling convention is used widely by the Windows API and
+COM applications. See the documentation for `__stdcall`_ on MSDN.
+
+.. _`__stdcall`: http://msdn.microsoft.com/en-us/library/zxk0tw93.aspx
+ }];
+}
+
+def FastCallDocs : Documentation {
+ let Category = DocCatCallingConvs;
+ let Content = [{
+On 32-bit x86 targets, this attribute changes the calling convention of a
+function to use ECX and EDX as register parameters and clear parameters off of
+the stack on return. This convention does not support variadic calls or
+unprototyped functions in C, and has no effect on x86_64 targets. This calling
+convention is supported primarily for compatibility with existing code. Users
+seeking register parameters should use the ``regparm`` attribute, which does
+not require callee-cleanup. See the documentation for `__fastcall`_ on MSDN.
+
+.. _`__fastcall`: http://msdn.microsoft.com/en-us/library/6xa169sk.aspx
+ }];
+}
+
+def ThisCallDocs : Documentation {
+ let Category = DocCatCallingConvs;
+ let Content = [{
+On 32-bit x86 targets, this attribute changes the calling convention of a
+function to use ECX for the first parameter (typically the implicit ``this``
+parameter of C++ methods) and clear parameters off of the stack on return. This
+convention does not support variadic calls or unprototyped functions in C, and
+has no effect on x86_64 targets. See the documentation for `__thiscall`_ on
+MSDN.
+
+.. _`__thiscall`: http://msdn.microsoft.com/en-us/library/ek8tkfbw.aspx
+ }];
+}
+
+def VectorCallDocs : Documentation {
+ let Category = DocCatCallingConvs;
+ let Content = [{
+On 32-bit x86 *and* x86_64 targets, this attribute changes the calling
+convention of a function to pass vector parameters in SSE registers.
+
+On 32-bit x86 targets, this calling convention is similar to ``__fastcall``.
+The first two integer parameters are passed in ECX and EDX. Subsequent integer
+parameters are passed in memory, and callee clears the stack. On x86_64
+targets, the callee does *not* clear the stack, and integer parameters are
+passed in RCX, RDX, R8, and R9 as is done for the default Windows x64 calling
+convention.
+
+On both 32-bit x86 and x86_64 targets, vector and floating point arguments are
+passed in XMM0-XMM5. Homogenous vector aggregates of up to four elements are
+passed in sequential SSE registers if enough are available. If AVX is enabled,
+256 bit vectors are passed in YMM0-YMM5. Any vector or aggregate type that
+cannot be passed in registers for any reason is passed by reference, which
+allows the caller to align the parameter memory.
+
+See the documentation for `__vectorcall`_ on MSDN for more details.
+
+.. _`__vectorcall`: http://msdn.microsoft.com/en-us/library/dn375768.aspx
+ }];
+}
+
def DocCatConsumed : DocumentationCategory<"Consumed Annotation Checking"> {
let Content = [{
Clang supports additional attributes for checking basic resource management
@@ -987,6 +1176,36 @@ Clang implements two kinds of checks with this attribute.
}];
}
+def AlignValueDocs : Documentation {
+ let Category = DocCatType;
+ let Content = [{
+The align_value attribute can be added to the typedef of a pointer type or the
+declaration of a variable of pointer or reference type. It specifies that the
+pointer will point to, or the reference will bind to, only objects with at
+least the provided alignment. This alignment value must be some positive power
+of 2.
+
+ .. code-block:: c
+
+ typedef double * aligned_double_ptr __attribute__((align_value(64)));
+ void foo(double & x __attribute__((align_value(128)),
+ aligned_double_ptr y) { ... }
+
+If the pointer value does not have the specified alignment at runtime, the
+behavior of the program is undefined.
+ }];
+}
+
+def FlagEnumDocs : Documentation {
+ let Category = DocCatType;
+ let Content = [{
+This attribute can be added to an enumerator to signal to the compiler that it
+is intended to be used as a flag type. This will cause the compiler to assume
+that the range of the type includes all of the values that you can get by
+manipulating bits of the enumerator when issuing warnings.
+ }];
+}
+
def MSInheritanceDocs : Documentation {
let Category = DocCatType;
let Heading = "__single_inhertiance, __multiple_inheritance, __virtual_inheritance";
@@ -1045,12 +1264,14 @@ 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.
+This attribute is incompatible with the ``always_inline`` and ``minsize``
+attributes.
}];
}
def LoopHintDocs : Documentation {
let Category = DocCatStmt;
+ let Heading = "#pragma clang loop";
let Content = [{
The ``#pragma clang loop`` directive allows loop optimization hints to be
specified for the subsequent loop. The directive allows vectorization,
@@ -1064,10 +1285,11 @@ for details.
def UnrollHintDocs : Documentation {
let Category = DocCatStmt;
+ let Heading = "#pragma unroll, #pragma nounroll";
let Content = [{
-Loop unrolling optimization hints can be specified with ``#pragma unroll``. The
-pragma is placed immediately before a for, while, do-while, or c++11 range-based
-for loop.
+Loop unrolling optimization hints can be specified with ``#pragma unroll`` and
+``#pragma nounroll``. The pragma is placed immediately before a for, while,
+do-while, or c++11 range-based for loop.
Specifying ``#pragma unroll`` without a parameter directs the loop unroller to
attempt to fully unroll the loop if the trip count is known at compile time:
@@ -1095,11 +1317,107 @@ enclosed in parentheses:
...
}
+Specifying ``#pragma nounroll`` indicates that the loop should not be unrolled:
+
+.. code-block:: c++
+
+ #pragma nounroll
+ for (...) {
+ ...
+ }
+
``#pragma unroll`` and ``#pragma unroll _value_`` have identical semantics to
-``#pragma clang loop unroll(enable)`` and ``#pragma clang loop
-unroll_count(_value_)`` respectively. See `language extensions
+``#pragma clang loop unroll(full)`` and
+``#pragma clang loop unroll_count(_value_)`` respectively. ``#pragma nounroll``
+is equivalent to ``#pragma clang loop unroll(disable)``. See
+`language extensions
<http://clang.llvm.org/docs/LanguageExtensions.html#extensions-for-loop-hint-optimizations>`_
for further details including limitations of the unroll hints.
}];
}
+def DocOpenCLAddressSpaces : DocumentationCategory<"OpenCL Address Spaces"> {
+ let Content = [{
+The address space qualifier may be used to specify the region of memory that is
+used to allocate the object. OpenCL supports the following address spaces:
+__generic(generic), __global(global), __local(local), __private(private),
+__constant(constant).
+
+ .. code-block:: c
+
+ __constant int c = ...;
+
+ __generic int* foo(global int* g) {
+ __local int* l;
+ private int p;
+ ...
+ return l;
+ }
+
+More details can be found in the OpenCL C language Spec v2.0, Section 6.5.
+ }];
+}
+
+def OpenCLAddressSpaceGenericDocs : Documentation {
+ let Category = DocOpenCLAddressSpaces;
+ let Heading = "__generic(generic)";
+ let Content = [{
+The generic address space attribute is only available with OpenCL v2.0 and later.
+It can be used with pointer types. Variables in global and local scope and
+function parameters in non-kernel functions can have the generic address space
+type attribute. It is intended to be a placeholder for any other address space
+except for '__constant' in OpenCL code which can be used with multiple address
+spaces.
+ }];
+}
+
+def OpenCLAddressSpaceConstantDocs : Documentation {
+ let Category = DocOpenCLAddressSpaces;
+ let Heading = "__constant(constant)";
+ let Content = [{
+The constant address space attribute signals that an object is located in
+a constant (non-modifiable) memory region. It is available to all work items.
+Any type can be annotated with the constant address space attribute. Objects
+with the constant address space qualifier can be declared in any scope and must
+have an initializer.
+ }];
+}
+
+def OpenCLAddressSpaceGlobalDocs : Documentation {
+ let Category = DocOpenCLAddressSpaces;
+ let Heading = "__global(global)";
+ let Content = [{
+The global address space attribute specifies that an object is allocated in
+global memory, which is accessible by all work items. The content stored in this
+memory area persists between kernel executions. Pointer types to the global
+address space are allowed as function parameters or local variables. Starting
+with OpenCL v2.0, the global address space can be used with global (program
+scope) variables and static local variable as well.
+ }];
+}
+
+def OpenCLAddressSpaceLocalDocs : Documentation {
+ let Category = DocOpenCLAddressSpaces;
+ let Heading = "__local(local)";
+ let Content = [{
+The local address space specifies that an object is allocated in the local (work
+group) memory area, which is accessible to all work items in the same work
+group. The content stored in this memory region is not accessible after
+the kernel execution ends. In a kernel function scope, any variable can be in
+the local address space. In other scopes, only pointer types to the local address
+space are allowed. Local address space variables cannot have an initializer.
+ }];
+}
+
+def OpenCLAddressSpacePrivateDocs : Documentation {
+ let Category = DocOpenCLAddressSpaces;
+ let Heading = "__private(private)";
+ let Content = [{
+The private address space specifies that an object is allocated in the private
+(work item) memory. Other work items cannot access the same memory area and its
+content is destroyed after work item execution ends. Local variables can be
+declared in the private address space. Function arguments are always in the
+private address space. Kernel function arguments of a pointer or an array type
+cannot point to the private address space.
+ }];
+}
diff --git a/include/clang/Basic/AttrKinds.h b/include/clang/Basic/AttrKinds.h
index 150a30e73d3f..f0b0a6445d40 100644
--- a/include/clang/Basic/AttrKinds.h
+++ b/include/clang/Basic/AttrKinds.h
@@ -12,8 +12,8 @@
///
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_ATTRKINDS_H
-#define LLVM_CLANG_ATTRKINDS_H
+#ifndef LLVM_CLANG_BASIC_ATTRKINDS_H
+#define LLVM_CLANG_BASIC_ATTRKINDS_H
namespace clang {
diff --git a/include/clang/Basic/Attributes.h b/include/clang/Basic/Attributes.h
index 5783b3bff510..a64dd5666b73 100644
--- a/include/clang/Basic/Attributes.h
+++ b/include/clang/Basic/Attributes.h
@@ -10,16 +10,14 @@
#ifndef LLVM_CLANG_BASIC_ATTRIBUTES_H
#define LLVM_CLANG_BASIC_ATTRIBUTES_H
-#include "llvm/ADT/Triple.h"
#include "clang/Basic/LangOptions.h"
+#include "llvm/ADT/Triple.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?
@@ -30,11 +28,11 @@ enum class AttrSyntax {
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);
+/// \brief Return the version number associated with the attribute if we
+/// recognize and implement the attribute specified by the given information.
+int hasAttribute(AttrSyntax Syntax, const IdentifierInfo *Scope,
+ const IdentifierInfo *Attr, const llvm::Triple &T,
+ const LangOptions &LangOpts);
} // end namespace clang
diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def
index e705382e11ca..098f5dacacbd 100644
--- a/include/clang/Basic/Builtins.def
+++ b/include/clang/Basic/Builtins.def
@@ -412,6 +412,7 @@ BUILTIN(__builtin_va_start, "vA.", "nt")
BUILTIN(__builtin_va_end, "vA", "n")
BUILTIN(__builtin_va_copy, "vAA", "n")
BUILTIN(__builtin_stdarg_start, "vA.", "n")
+BUILTIN(__builtin_assume_aligned, "v*vC*z.", "nc")
BUILTIN(__builtin_bcmp, "iv*v*z", "n")
BUILTIN(__builtin_bcopy, "vv*v*z", "n")
BUILTIN(__builtin_bzero, "vv*z", "nF")
@@ -496,6 +497,7 @@ BUILTIN(__builtin_unreachable, "v", "nr")
BUILTIN(__builtin_shufflevector, "v." , "nc")
BUILTIN(__builtin_convertvector, "v." , "nct")
BUILTIN(__builtin_alloca, "v*z" , "n")
+BUILTIN(__builtin_call_with_static_chain, "v.", "nt")
// "Overloaded" Atomic operator builtins. These are overloaded to support data
// types of i8, i16, i32, i64, and i128. The front-end sees calls to the
@@ -540,6 +542,12 @@ BUILTIN(__sync_fetch_and_xor_4, "iiD*i.", "tn")
BUILTIN(__sync_fetch_and_xor_8, "LLiLLiD*LLi.", "tn")
BUILTIN(__sync_fetch_and_xor_16, "LLLiLLLiD*LLLi.", "tn")
+BUILTIN(__sync_fetch_and_nand, "v.", "t")
+BUILTIN(__sync_fetch_and_nand_1, "ccD*c.", "tn")
+BUILTIN(__sync_fetch_and_nand_2, "ssD*s.", "tn")
+BUILTIN(__sync_fetch_and_nand_4, "iiD*i.", "tn")
+BUILTIN(__sync_fetch_and_nand_8, "LLiLLiD*LLi.", "tn")
+BUILTIN(__sync_fetch_and_nand_16, "LLLiLLLiD*LLLi.", "tn")
BUILTIN(__sync_add_and_fetch, "v.", "t")
BUILTIN(__sync_add_and_fetch_1, "ccD*c.", "tn")
@@ -576,6 +584,13 @@ BUILTIN(__sync_xor_and_fetch_4, "iiD*i.", "tn")
BUILTIN(__sync_xor_and_fetch_8, "LLiLLiD*LLi.", "tn")
BUILTIN(__sync_xor_and_fetch_16, "LLLiLLLiD*LLLi.", "tn")
+BUILTIN(__sync_nand_and_fetch, "v.", "t")
+BUILTIN(__sync_nand_and_fetch_1, "ccD*c.", "tn")
+BUILTIN(__sync_nand_and_fetch_2, "ssD*s.", "tn")
+BUILTIN(__sync_nand_and_fetch_4, "iiD*i.", "tn")
+BUILTIN(__sync_nand_and_fetch_8, "LLiLLiD*LLi.", "tn")
+BUILTIN(__sync_nand_and_fetch_16, "LLLiLLLiD*LLLi.", "tn")
+
BUILTIN(__sync_bool_compare_and_swap, "v.", "t")
BUILTIN(__sync_bool_compare_and_swap_1, "bcD*cc.", "tn")
BUILTIN(__sync_bool_compare_and_swap_2, "bsD*ss.", "tn")
@@ -689,6 +704,7 @@ 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)
+LANGBUILTIN(__readfsdword, "ULiULi", "n", ALL_MS_LANGUAGES)
// C99 library functions
// C99 stdlib.h
@@ -1173,6 +1189,9 @@ LIBBUILTIN(_Block_object_dispose, "vvC*iC", "f", "Blocks.h", ALL_LANGUAGES)
// Annotation function
BUILTIN(__builtin_annotation, "v.", "tn")
+// Invariants
+BUILTIN(__builtin_assume, "vb", "n")
+
// Multiprecision Arithmetic Builtins.
BUILTIN(__builtin_addcb, "UcUcCUcCUcCUc*", "n")
BUILTIN(__builtin_addcs, "UsUsCUsCUsCUs*", "n")
diff --git a/include/clang/Basic/Builtins.h b/include/clang/Basic/Builtins.h
index f9d30e40560a..3ce2255c8646 100644
--- a/include/clang/Basic/Builtins.h
+++ b/include/clang/Basic/Builtins.h
@@ -29,7 +29,7 @@ namespace clang {
class ASTContext;
class QualType;
class LangOptions;
-
+
enum LanguageID {
GNU_LANG = 0x1, // builtin requires GNU mode.
C_LANG = 0x2, // builtin for c only.
@@ -40,7 +40,7 @@ namespace clang {
ALL_GNU_LANGUAGES = ALL_LANGUAGES | GNU_LANG, // builtin requires GNU mode.
ALL_MS_LANGUAGES = ALL_LANGUAGES | MS_LANG // builtin requires MS mode.
};
-
+
namespace Builtin {
enum ID {
NotBuiltin = 0, // This is not a builtin function.
diff --git a/include/clang/Basic/BuiltinsAArch64.def b/include/clang/Basic/BuiltinsAArch64.def
index 695ecf9da5f8..9d223c3e8516 100644
--- a/include/clang/Basic/BuiltinsAArch64.def
+++ b/include/clang/Basic/BuiltinsAArch64.def
@@ -50,4 +50,7 @@ BUILTIN(__builtin_arm_dmb, "vUi", "nc")
BUILTIN(__builtin_arm_dsb, "vUi", "nc")
BUILTIN(__builtin_arm_isb, "vUi", "nc")
+// Prefetch
+BUILTIN(__builtin_arm_prefetch, "vvC*UiUiUiUi", "nc")
+
#undef BUILTIN
diff --git a/include/clang/Basic/BuiltinsARM.def b/include/clang/Basic/BuiltinsARM.def
index 2e5eac694fc2..9091ad4d7581 100644
--- a/include/clang/Basic/BuiltinsARM.def
+++ b/include/clang/Basic/BuiltinsARM.def
@@ -74,13 +74,19 @@ BUILTIN(__builtin_arm_wfe, "v", "")
BUILTIN(__builtin_arm_wfi, "v", "")
BUILTIN(__builtin_arm_sev, "v", "")
BUILTIN(__builtin_arm_sevl, "v", "")
+BUILTIN(__builtin_arm_dbg, "vUi", "")
// Data barrier
BUILTIN(__builtin_arm_dmb, "vUi", "nc")
BUILTIN(__builtin_arm_dsb, "vUi", "nc")
BUILTIN(__builtin_arm_isb, "vUi", "nc")
+// Prefetch
+BUILTIN(__builtin_arm_prefetch, "vvC*UiUi", "nc")
+
// MSVC
+LANGBUILTIN(__emit, "vIUiC", "", ALL_MS_LANGUAGES)
+
LANGBUILTIN(__yield, "v", "", ALL_MS_LANGUAGES)
LANGBUILTIN(__wfe, "v", "", ALL_MS_LANGUAGES)
LANGBUILTIN(__wfi, "v", "", ALL_MS_LANGUAGES)
diff --git a/include/clang/Basic/BuiltinsLe64.def b/include/clang/Basic/BuiltinsLe64.def
new file mode 100644
index 000000000000..532860603c29
--- /dev/null
+++ b/include/clang/Basic/BuiltinsLe64.def
@@ -0,0 +1,19 @@
+//==- BuiltinsLe64.def - Le64 Builtin function database ----------*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the Le64-specific builtin function database. Users of this
+// file must define the BUILTIN macro to make use of this information.
+//
+//===----------------------------------------------------------------------===//
+
+// The format of this database matches clang/Basic/Builtins.def.
+
+BUILTIN(__clear_cache, "vv*v*", "i")
+
+#undef BUILTIN
diff --git a/include/clang/Basic/BuiltinsNVPTX.def b/include/clang/Basic/BuiltinsNVPTX.def
index 7e9b5eea8325..9c920dce5cab 100644
--- a/include/clang/Basic/BuiltinsNVPTX.def
+++ b/include/clang/Basic/BuiltinsNVPTX.def
@@ -139,8 +139,8 @@ BUILTIN(__nvvm_brev64, "ULLiULLi", "")
// Sad
-BUILTIN(__nvvm_sad_i, "iii", "")
-BUILTIN(__nvvm_sad_ui, "UiUiUi", "")
+BUILTIN(__nvvm_sad_i, "iiii", "")
+BUILTIN(__nvvm_sad_ui, "UiUiUiUi", "")
// Floor, Ceil
@@ -255,19 +255,19 @@ BUILTIN(__nvvm_rsqrt_approx_d, "dd", "")
// Add
-BUILTIN(__nvvm_add_rn_ftz_f, "ff", "")
-BUILTIN(__nvvm_add_rn_f, "ff", "")
-BUILTIN(__nvvm_add_rz_ftz_f, "ff", "")
-BUILTIN(__nvvm_add_rz_f, "ff", "")
-BUILTIN(__nvvm_add_rm_ftz_f, "ff", "")
-BUILTIN(__nvvm_add_rm_f, "ff", "")
-BUILTIN(__nvvm_add_rp_ftz_f, "ff", "")
-BUILTIN(__nvvm_add_rp_f, "ff", "")
-
-BUILTIN(__nvvm_add_rn_d, "dd", "")
-BUILTIN(__nvvm_add_rz_d, "dd", "")
-BUILTIN(__nvvm_add_rm_d, "dd", "")
-BUILTIN(__nvvm_add_rp_d, "dd", "")
+BUILTIN(__nvvm_add_rn_ftz_f, "fff", "")
+BUILTIN(__nvvm_add_rn_f, "fff", "")
+BUILTIN(__nvvm_add_rz_ftz_f, "fff", "")
+BUILTIN(__nvvm_add_rz_f, "fff", "")
+BUILTIN(__nvvm_add_rm_ftz_f, "fff", "")
+BUILTIN(__nvvm_add_rm_f, "fff", "")
+BUILTIN(__nvvm_add_rp_ftz_f, "fff", "")
+BUILTIN(__nvvm_add_rp_f, "fff", "")
+
+BUILTIN(__nvvm_add_rn_d, "ddd", "")
+BUILTIN(__nvvm_add_rz_d, "ddd", "")
+BUILTIN(__nvvm_add_rm_d, "ddd", "")
+BUILTIN(__nvvm_add_rp_d, "ddd", "")
// Convert
diff --git a/include/clang/Basic/BuiltinsPPC.def b/include/clang/Basic/BuiltinsPPC.def
index 8a751e4ce846..e42af4244160 100644
--- a/include/clang/Basic/BuiltinsPPC.def
+++ b/include/clang/Basic/BuiltinsPPC.def
@@ -204,6 +204,25 @@ BUILTIN(__builtin_altivec_vcmpgtsw_p, "iiV4SiV4Si", "")
BUILTIN(__builtin_altivec_vcmpgtuw_p, "iiV4UiV4Ui", "")
BUILTIN(__builtin_altivec_vcmpgtfp_p, "iiV4fV4f", "")
+// VSX built-ins.
+
+BUILTIN(__builtin_vsx_lxvd2x, "V2divC*", "")
+BUILTIN(__builtin_vsx_lxvw4x, "V4iivC*", "")
+
+BUILTIN(__builtin_vsx_stxvd2x, "vV2div*", "")
+BUILTIN(__builtin_vsx_stxvw4x, "vV4iiv*", "")
+
+BUILTIN(__builtin_vsx_xvmaxdp, "V2dV2dV2d", "")
+BUILTIN(__builtin_vsx_xvmaxsp, "V4fV4fV4f", "")
+BUILTIN(__builtin_vsx_xsmaxdp, "ddd", "")
+
+BUILTIN(__builtin_vsx_xvmindp, "V2dV2dV2d", "")
+BUILTIN(__builtin_vsx_xvminsp, "V4fV4fV4f", "")
+BUILTIN(__builtin_vsx_xsmindp, "ddd", "")
+
+BUILTIN(__builtin_vsx_xvdivdp, "V2dV2dV2d", "")
+BUILTIN(__builtin_vsx_xvdivsp, "V4fV4fV4f", "")
+
// FIXME: Obviously incomplete.
#undef BUILTIN
diff --git a/include/clang/Basic/BuiltinsR600.def b/include/clang/Basic/BuiltinsR600.def
index 49135ccb056d..84fc4fae4eab 100644
--- a/include/clang/Basic/BuiltinsR600.def
+++ b/include/clang/Basic/BuiltinsR600.def
@@ -16,8 +16,8 @@
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_fmas, "ddddb", "nc")
+BUILTIN(__builtin_amdgpu_div_fmasf, "ffffb", "nc")
BUILTIN(__builtin_amdgpu_div_fixup, "dddd", "nc")
BUILTIN(__builtin_amdgpu_div_fixupf, "ffff", "nc")
BUILTIN(__builtin_amdgpu_trig_preop, "ddi", "nc")
@@ -28,5 +28,9 @@ BUILTIN(__builtin_amdgpu_rsq, "dd", "nc")
BUILTIN(__builtin_amdgpu_rsqf, "ff", "nc")
BUILTIN(__builtin_amdgpu_rsq_clamped, "dd", "nc")
BUILTIN(__builtin_amdgpu_rsq_clampedf, "ff", "nc")
+BUILTIN(__builtin_amdgpu_ldexp, "ddi", "nc")
+BUILTIN(__builtin_amdgpu_ldexpf, "ffi", "nc")
+BUILTIN(__builtin_amdgpu_class, "bdi", "nc")
+BUILTIN(__builtin_amdgpu_classf, "bfi", "nc")
#undef BUILTIN
diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def
index 1f377a8ab1de..eb6803b141b7 100644
--- a/include/clang/Basic/BuiltinsX86.def
+++ b/include/clang/Basic/BuiltinsX86.def
@@ -187,13 +187,45 @@ BUILTIN(__builtin_ia32_ucomisdgt, "iV2dV2d", "")
BUILTIN(__builtin_ia32_ucomisdge, "iV2dV2d", "")
BUILTIN(__builtin_ia32_ucomisdneq, "iV2dV2d", "")
BUILTIN(__builtin_ia32_cmpps, "V4fV4fV4fIc", "")
+BUILTIN(__builtin_ia32_cmpeqps, "V4fV4fV4f", "")
+BUILTIN(__builtin_ia32_cmpltps, "V4fV4fV4f", "")
+BUILTIN(__builtin_ia32_cmpleps, "V4fV4fV4f", "")
+BUILTIN(__builtin_ia32_cmpunordps, "V4fV4fV4f", "")
+BUILTIN(__builtin_ia32_cmpneqps, "V4fV4fV4f", "")
+BUILTIN(__builtin_ia32_cmpnltps, "V4fV4fV4f", "")
+BUILTIN(__builtin_ia32_cmpnleps, "V4fV4fV4f", "")
+BUILTIN(__builtin_ia32_cmpordps, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_cmpss, "V4fV4fV4fIc", "")
+BUILTIN(__builtin_ia32_cmpeqss, "V4fV4fV4f", "")
+BUILTIN(__builtin_ia32_cmpltss, "V4fV4fV4f", "")
+BUILTIN(__builtin_ia32_cmpless, "V4fV4fV4f", "")
+BUILTIN(__builtin_ia32_cmpunordss, "V4fV4fV4f", "")
+BUILTIN(__builtin_ia32_cmpneqss, "V4fV4fV4f", "")
+BUILTIN(__builtin_ia32_cmpnltss, "V4fV4fV4f", "")
+BUILTIN(__builtin_ia32_cmpnless, "V4fV4fV4f", "")
+BUILTIN(__builtin_ia32_cmpordss, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_minps, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_maxps, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_minss, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_maxss, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_cmppd, "V2dV2dV2dIc", "")
+BUILTIN(__builtin_ia32_cmpeqpd, "V2dV2dV2d", "")
+BUILTIN(__builtin_ia32_cmpltpd, "V2dV2dV2d", "")
+BUILTIN(__builtin_ia32_cmplepd, "V2dV2dV2d", "")
+BUILTIN(__builtin_ia32_cmpunordpd, "V2dV2dV2d", "")
+BUILTIN(__builtin_ia32_cmpneqpd, "V2dV2dV2d", "")
+BUILTIN(__builtin_ia32_cmpnltpd, "V2dV2dV2d", "")
+BUILTIN(__builtin_ia32_cmpnlepd, "V2dV2dV2d", "")
+BUILTIN(__builtin_ia32_cmpordpd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_cmpsd, "V2dV2dV2dIc", "")
+BUILTIN(__builtin_ia32_cmpeqsd, "V2dV2dV2d", "")
+BUILTIN(__builtin_ia32_cmpltsd, "V2dV2dV2d", "")
+BUILTIN(__builtin_ia32_cmplesd, "V2dV2dV2d", "")
+BUILTIN(__builtin_ia32_cmpunordsd, "V2dV2dV2d", "")
+BUILTIN(__builtin_ia32_cmpneqsd, "V2dV2dV2d", "")
+BUILTIN(__builtin_ia32_cmpnltsd, "V2dV2dV2d", "")
+BUILTIN(__builtin_ia32_cmpnlesd, "V2dV2dV2d", "")
+BUILTIN(__builtin_ia32_cmpordsd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_minpd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_maxpd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_minsd, "V2dV2dV2d", "")
@@ -303,12 +335,12 @@ BUILTIN(__builtin_ia32_monitor, "vv*UiUi", "")
BUILTIN(__builtin_ia32_mwait, "vUiUi", "")
BUILTIN(__builtin_ia32_lddqu, "V16ccC*", "")
BUILTIN(__builtin_ia32_palignr128, "V16cV16cV16cIc", "")
-BUILTIN(__builtin_ia32_insertps128, "V4fV4fV4fi", "")
+BUILTIN(__builtin_ia32_insertps128, "V4fV4fV4fIc", "")
BUILTIN(__builtin_ia32_pblendvb128, "V16cV16cV16cV16c", "")
-BUILTIN(__builtin_ia32_pblendw128, "V8sV8sV8sIi", "")
-BUILTIN(__builtin_ia32_blendpd, "V2dV2dV2dIi", "")
-BUILTIN(__builtin_ia32_blendps, "V4fV4fV4fIi", "")
+BUILTIN(__builtin_ia32_pblendw128, "V8sV8sV8sIc", "")
+BUILTIN(__builtin_ia32_blendpd, "V2dV2dV2dIc", "")
+BUILTIN(__builtin_ia32_blendps, "V4fV4fV4fIc", "")
BUILTIN(__builtin_ia32_blendvpd, "V2dV2dV2dV2d", "")
BUILTIN(__builtin_ia32_blendvps, "V4fV4fV4fV4f", "")
@@ -339,13 +371,13 @@ BUILTIN(__builtin_ia32_roundps, "V4fV4fi", "")
BUILTIN(__builtin_ia32_roundss, "V4fV4fV4fi", "")
BUILTIN(__builtin_ia32_roundsd, "V2dV2dV2di", "")
BUILTIN(__builtin_ia32_roundpd, "V2dV2di", "")
-BUILTIN(__builtin_ia32_dpps, "V4fV4fV4fi", "")
-BUILTIN(__builtin_ia32_dppd, "V2dV2dV2di", "")
+BUILTIN(__builtin_ia32_dpps, "V4fV4fV4fIc", "")
+BUILTIN(__builtin_ia32_dppd, "V2dV2dV2dIc", "")
BUILTIN(__builtin_ia32_movntdqa, "V2LLiV2LLi*", "")
BUILTIN(__builtin_ia32_ptestz128, "iV2LLiV2LLi", "")
BUILTIN(__builtin_ia32_ptestc128, "iV2LLiV2LLi", "")
BUILTIN(__builtin_ia32_ptestnzc128, "iV2LLiV2LLi", "")
-BUILTIN(__builtin_ia32_mpsadbw128, "V16cV16cV16ci", "")
+BUILTIN(__builtin_ia32_mpsadbw128, "V16cV16cV16cIc", "")
BUILTIN(__builtin_ia32_phminposuw128, "V8sV8s", "")
// SSE 4.2
@@ -404,13 +436,13 @@ BUILTIN(__builtin_ia32_vpermilvarpd, "V2dV2dV2LLi", "")
BUILTIN(__builtin_ia32_vpermilvarps, "V4fV4fV4i", "")
BUILTIN(__builtin_ia32_vpermilvarpd256, "V4dV4dV4LLi", "")
BUILTIN(__builtin_ia32_vpermilvarps256, "V8fV8fV8i", "")
-BUILTIN(__builtin_ia32_blendpd256, "V4dV4dV4dIi", "")
-BUILTIN(__builtin_ia32_blendps256, "V8fV8fV8fIi", "")
+BUILTIN(__builtin_ia32_blendpd256, "V4dV4dV4dIc", "")
+BUILTIN(__builtin_ia32_blendps256, "V8fV8fV8fIc", "")
BUILTIN(__builtin_ia32_blendvpd256, "V4dV4dV4dV4d", "")
BUILTIN(__builtin_ia32_blendvps256, "V8fV8fV8fV8f", "")
-BUILTIN(__builtin_ia32_dpps256, "V8fV8fV8fIi", "")
-BUILTIN(__builtin_ia32_cmppd256, "V4dV4dV4dc", "")
-BUILTIN(__builtin_ia32_cmpps256, "V8fV8fV8fc", "")
+BUILTIN(__builtin_ia32_dpps256, "V8fV8fV8fIc", "")
+BUILTIN(__builtin_ia32_cmppd256, "V4dV4dV4dIc", "")
+BUILTIN(__builtin_ia32_cmpps256, "V8fV8fV8fIc", "")
BUILTIN(__builtin_ia32_vextractf128_pd256, "V2dV4dIc", "")
BUILTIN(__builtin_ia32_vextractf128_ps256, "V4fV8fIc", "")
BUILTIN(__builtin_ia32_vextractf128_si256, "V4iV8iIc", "")
@@ -472,7 +504,7 @@ BUILTIN(__builtin_ia32_maskstorepd256, "vV4d*V4dV4d", "")
BUILTIN(__builtin_ia32_maskstoreps256, "vV8f*V8fV8f", "")
// AVX2
-BUILTIN(__builtin_ia32_mpsadbw256, "V32cV32cV32ci", "")
+BUILTIN(__builtin_ia32_mpsadbw256, "V32cV32cV32cIc", "")
BUILTIN(__builtin_ia32_pabsb256, "V32cV32c", "")
BUILTIN(__builtin_ia32_pabsw256, "V16sV16s", "")
BUILTIN(__builtin_ia32_pabsd256, "V8iV8i", "")
@@ -492,7 +524,7 @@ BUILTIN(__builtin_ia32_palignr256, "V32cV32cV32cIc", "")
BUILTIN(__builtin_ia32_pavgb256, "V32cV32cV32c", "")
BUILTIN(__builtin_ia32_pavgw256, "V16sV16sV16s", "")
BUILTIN(__builtin_ia32_pblendvb256, "V32cV32cV32cV32c", "")
-BUILTIN(__builtin_ia32_pblendw256, "V16sV16sV16sIi", "")
+BUILTIN(__builtin_ia32_pblendw256, "V16sV16sV16sIc", "")
BUILTIN(__builtin_ia32_phaddw256, "V16sV16sV16s", "")
BUILTIN(__builtin_ia32_phaddd256, "V8iV8iV8i", "")
BUILTIN(__builtin_ia32_phaddsw256, "V16sV16sV16s", "")
@@ -559,8 +591,8 @@ BUILTIN(__builtin_ia32_vbroadcastss_ps, "V4fV4f", "")
BUILTIN(__builtin_ia32_vbroadcastss_ps256, "V8fV4f", "")
BUILTIN(__builtin_ia32_vbroadcastsd_pd256, "V4dV2d", "")
BUILTIN(__builtin_ia32_vbroadcastsi256, "V4LLiV2LLi", "")
-BUILTIN(__builtin_ia32_pblendd128, "V4iV4iV4iIi", "")
-BUILTIN(__builtin_ia32_pblendd256, "V8iV8iV8iIi", "")
+BUILTIN(__builtin_ia32_pblendd128, "V4iV4iV4iIc", "")
+BUILTIN(__builtin_ia32_pblendd256, "V8iV8iV8iIc", "")
BUILTIN(__builtin_ia32_pbroadcastb256, "V32cV16c", "")
BUILTIN(__builtin_ia32_pbroadcastw256, "V16sV8s", "")
BUILTIN(__builtin_ia32_pbroadcastd256, "V8iV4i", "")
@@ -615,14 +647,34 @@ BUILTIN(__builtin_ia32_gatherq_d256, "V4iV4iV4iC*V4LLiV4iIc", "")
// F16C
BUILTIN(__builtin_ia32_vcvtps2ph, "V8sV4fIi", "")
BUILTIN(__builtin_ia32_vcvtps2ph256, "V8sV8fIi", "")
+BUILTIN(__builtin_ia32_vcvtps2ph512, "V16sV16fIi", "")
BUILTIN(__builtin_ia32_vcvtph2ps, "V4fV8s", "")
BUILTIN(__builtin_ia32_vcvtph2ps256, "V8fV8s", "")
+BUILTIN(__builtin_ia32_vcvtph2ps512, "V16fV16s", "")
// RDRAND
BUILTIN(__builtin_ia32_rdrand16_step, "UiUs*", "")
BUILTIN(__builtin_ia32_rdrand32_step, "UiUi*", "")
BUILTIN(__builtin_ia32_rdrand64_step, "UiULLi*", "")
+// FSGSBASE
+BUILTIN(__builtin_ia32_rdfsbase32, "Ui", "")
+BUILTIN(__builtin_ia32_rdfsbase64, "ULLi", "")
+BUILTIN(__builtin_ia32_rdgsbase32, "Ui", "")
+BUILTIN(__builtin_ia32_rdgsbase64, "ULLi", "")
+BUILTIN(__builtin_ia32_wrfsbase32, "vUi", "")
+BUILTIN(__builtin_ia32_wrfsbase64, "vULLi", "")
+BUILTIN(__builtin_ia32_wrgsbase32, "vUi", "")
+BUILTIN(__builtin_ia32_wrgsbase64, "vULLi", "")
+
+// ADX
+BUILTIN(__builtin_ia32_addcarryx_u32, "UcUcUiUiUi*", "")
+BUILTIN(__builtin_ia32_addcarryx_u64, "UcUcULLiULLiULLi*", "")
+BUILTIN(__builtin_ia32_addcarry_u32, "UcUcUiUiUi*", "")
+BUILTIN(__builtin_ia32_addcarry_u64, "UcUcULLiULLiULLi*", "")
+BUILTIN(__builtin_ia32_subborrow_u32, "UcUcUiUiUi*", "")
+BUILTIN(__builtin_ia32_subborrow_u64, "UcUcULLiULLiULLi*", "")
+
// RDSEED
BUILTIN(__builtin_ia32_rdseed16_step, "UiUs*", "")
BUILTIN(__builtin_ia32_rdseed32_step, "UiUi*", "")
@@ -653,7 +705,7 @@ BUILTIN(__builtin_ia32_sha256rnds2, "V4iV4iV4iV4i", "")
BUILTIN(__builtin_ia32_sha256msg1, "V4iV4iV4i", "")
BUILTIN(__builtin_ia32_sha256msg2, "V4iV4iV4i", "")
-// FMA4
+// FMA
BUILTIN(__builtin_ia32_vfmaddps, "V4fV4fV4fV4f", "")
BUILTIN(__builtin_ia32_vfmaddpd, "V2dV2dV2dV2d", "")
BUILTIN(__builtin_ia32_vfmaddss, "V4fV4fV4fV4f", "")
@@ -686,6 +738,12 @@ BUILTIN(__builtin_ia32_vfmaddsubps256, "V8fV8fV8fV8f", "")
BUILTIN(__builtin_ia32_vfmaddsubpd256, "V4dV4dV4dV4d", "")
BUILTIN(__builtin_ia32_vfmsubaddps256, "V8fV8fV8fV8f", "")
BUILTIN(__builtin_ia32_vfmsubaddpd256, "V4dV4dV4dV4d", "")
+BUILTIN(__builtin_ia32_vfmaddpd512_mask, "V8dV8dV8dV8dUci", "")
+BUILTIN(__builtin_ia32_vfmsubpd512_mask, "V8dV8dV8dV8dUci", "")
+BUILTIN(__builtin_ia32_vfnmaddpd512_mask, "V8dV8dV8dV8dUci", "")
+BUILTIN(__builtin_ia32_vfmaddps512_mask, "V16fV16fV16fV16fUsi", "")
+BUILTIN(__builtin_ia32_vfmsubps512_mask, "V16fV16fV16fV16fUsi", "")
+BUILTIN(__builtin_ia32_vfnmaddps512_mask, "V16fV16fV16fV16fUsi", "")
// XOP
BUILTIN(__builtin_ia32_vpmacssww, "V8sV8sV8sV8s", "")
@@ -761,4 +819,119 @@ BUILTIN(__builtin_ia32_rdpmc, "ULLii", "")
BUILTIN(__builtin_ia32_rdtsc, "ULLi", "")
BUILTIN(__builtin_ia32_rdtscp, "ULLiUi*", "")
+// AVX-512
+BUILTIN(__builtin_ia32_sqrtpd512_mask, "V8dV8dV8dUciC", "")
+BUILTIN(__builtin_ia32_sqrtps512_mask, "V16fV16fV16fUsiC", "")
+BUILTIN(__builtin_ia32_rsqrt14sd_mask, "V2dV2dV2dV2dUc", "")
+BUILTIN(__builtin_ia32_rsqrt14ss_mask, "V4fV4fV4fV4fUc", "")
+BUILTIN(__builtin_ia32_rsqrt14pd512_mask, "V8dV8dV8dUc", "")
+BUILTIN(__builtin_ia32_rsqrt14ps512_mask, "V16fV16fV16fUs", "")
+BUILTIN(__builtin_ia32_rsqrt28sd_mask, "V2dV2dV2dV2dUciC", "")
+BUILTIN(__builtin_ia32_rsqrt28ss_mask, "V4fV4fV4fV4fUciC", "")
+BUILTIN(__builtin_ia32_rsqrt28pd_mask, "V8dV8dV8dUciC", "")
+BUILTIN(__builtin_ia32_rsqrt28ps_mask, "V16fV16fV16fUsiC", "")
+BUILTIN(__builtin_ia32_rcp14sd_mask, "V2dV2dV2dV2dUc", "")
+BUILTIN(__builtin_ia32_rcp14ss_mask, "V4fV4fV4fV4fUc", "")
+BUILTIN(__builtin_ia32_rcp14pd512_mask, "V8dV8dV8dUc", "")
+BUILTIN(__builtin_ia32_rcp14ps512_mask, "V16fV16fV16fUs", "")
+BUILTIN(__builtin_ia32_rcp28sd_mask, "V2dV2dV2dV2dUciC", "")
+BUILTIN(__builtin_ia32_rcp28ss_mask, "V4fV4fV4fV4fUciC", "")
+BUILTIN(__builtin_ia32_rcp28pd_mask, "V8dV8dV8dUciC", "")
+BUILTIN(__builtin_ia32_rcp28ps_mask, "V16fV16fV16fUsiC", "")
+BUILTIN(__builtin_ia32_cvttps2dq512_mask, "V16iV16fV16iUsiC", "")
+BUILTIN(__builtin_ia32_cvttps2udq512_mask, "V16iV16fV16iUsiC", "")
+BUILTIN(__builtin_ia32_cvttpd2dq512_mask, "V8iV8dV8iUciC", "")
+BUILTIN(__builtin_ia32_cvttpd2udq512_mask, "V8iV8dV8iUciC", "")
+BUILTIN(__builtin_ia32_cmpps512_mask, "UsV16fV16fiCUsi", "")
+BUILTIN(__builtin_ia32_pcmpeqb512_mask, "LLiV64cV64cLLi", "")
+BUILTIN(__builtin_ia32_pcmpeqd512_mask, "sV16iV16is", "")
+BUILTIN(__builtin_ia32_pcmpeqq512_mask, "cV8LLiV8LLic", "")
+BUILTIN(__builtin_ia32_pcmpeqw512_mask, "iV32sV32si", "")
+BUILTIN(__builtin_ia32_pcmpeqb256_mask, "iV32cV32ci", "")
+BUILTIN(__builtin_ia32_pcmpeqd256_mask, "cV8iV8ic", "")
+BUILTIN(__builtin_ia32_pcmpeqq256_mask, "cV4LLiV4LLic", "")
+BUILTIN(__builtin_ia32_pcmpeqw256_mask, "sV16sV16ss", "")
+BUILTIN(__builtin_ia32_pcmpeqb128_mask, "sV16cV16cs", "")
+BUILTIN(__builtin_ia32_pcmpeqd128_mask, "cV4iV4ic", "")
+BUILTIN(__builtin_ia32_pcmpeqq128_mask, "cV2LLiV2LLic", "")
+BUILTIN(__builtin_ia32_pcmpeqw128_mask, "cV8sV8sc", "")
+BUILTIN(__builtin_ia32_cmppd512_mask, "UcV8dV8diCUci", "")
+BUILTIN(__builtin_ia32_rndscaleps_mask, "V16fV16fiCV16fUsiC", "")
+BUILTIN(__builtin_ia32_rndscalepd_mask, "V8dV8diCV8dUciC", "")
+BUILTIN(__builtin_ia32_cvtps2dq512_mask, "V16iV16fV16iUsiC", "")
+BUILTIN(__builtin_ia32_cvtpd2dq512_mask, "V8iV8dV8iUciC", "")
+BUILTIN(__builtin_ia32_cvtps2udq512_mask, "V16iV16fV16iUsiC", "")
+BUILTIN(__builtin_ia32_cvtpd2udq512_mask, "V8iV8dV8iUciC", "")
+BUILTIN(__builtin_ia32_minps512_mask, "V16fV16fV16fV16fUsiC", "")
+BUILTIN(__builtin_ia32_minpd512_mask, "V8dV8dV8dV8dUciC", "")
+BUILTIN(__builtin_ia32_maxps512_mask, "V16fV16fV16fV16fUsiC", "")
+BUILTIN(__builtin_ia32_maxpd512_mask, "V8dV8dV8dV8dUciC", "")
+BUILTIN(__builtin_ia32_cvtdq2ps512_mask, "V16fV16iV16fUsiC", "")
+BUILTIN(__builtin_ia32_cvtudq2ps512_mask, "V16fV16iV16fUsiC", "")
+BUILTIN(__builtin_ia32_cvtdq2pd512_mask, "V8dV8iV8dUc", "")
+BUILTIN(__builtin_ia32_cvtudq2pd512_mask, "V8dV8iV8dUc", "")
+BUILTIN(__builtin_ia32_cvtpd2ps512_mask, "V8fV8dV8fUciC", "")
+BUILTIN(__builtin_ia32_vcvtps2ph512_mask, "V16sV16fiCV16sUs", "")
+BUILTIN(__builtin_ia32_vcvtph2ps512_mask, "V16fV16sV16fUsiC", "")
+BUILTIN(__builtin_ia32_pabsd512_mask, "V16iV16iV16iUs", "")
+BUILTIN(__builtin_ia32_pabsq512_mask, "V8LLiV8LLiV8LLiUc", "")
+BUILTIN(__builtin_ia32_pmaxsd512_mask, "V16iV16iV16iV16iUs", "")
+BUILTIN(__builtin_ia32_pmaxsq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "")
+BUILTIN(__builtin_ia32_pmaxud512_mask, "V16iV16iV16iV16iUs", "")
+BUILTIN(__builtin_ia32_pmaxuq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "")
+BUILTIN(__builtin_ia32_pminsd512_mask, "V16iV16iV16iV16iUs", "")
+BUILTIN(__builtin_ia32_pminsq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "")
+BUILTIN(__builtin_ia32_pminud512_mask, "V16iV16iV16iV16iUs", "")
+BUILTIN(__builtin_ia32_pminuq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "")
+BUILTIN(__builtin_ia32_pmuldq512_mask, "V8LLiV16iV16iV8LLiUc", "")
+BUILTIN(__builtin_ia32_pmuludq512_mask, "V8LLiV16iV16iV8LLiUc", "")
+BUILTIN(__builtin_ia32_blendmd_512_mask, "V16iV16iV16iUs", "")
+BUILTIN(__builtin_ia32_blendmq_512_mask, "V8LLiV8LLiV8LLiUc", "")
+BUILTIN(__builtin_ia32_blendmps_512_mask, "V16fV16fV16fUs", "")
+BUILTIN(__builtin_ia32_blendmpd_512_mask, "V8dV8dV8dUc", "")
+BUILTIN(__builtin_ia32_ptestmd512, "UsV16iV16iUs", "")
+BUILTIN(__builtin_ia32_ptestmq512, "UcV8LLiV8LLiUc", "")
+BUILTIN(__builtin_ia32_pbroadcastd512_gpr_mask, "V16iiV16iUs", "")
+BUILTIN(__builtin_ia32_pbroadcastq512_gpr_mask, "V8LLiLLiV8LLiUc", "")
+BUILTIN(__builtin_ia32_pbroadcastq512_mem_mask, "V8LLiLLiV8LLiUc", "")
+BUILTIN(__builtin_ia32_loaddqusi512_mask, "V16ivC*V16iUs", "")
+BUILTIN(__builtin_ia32_loaddqudi512_mask, "V8LLivC*V8LLiUc", "")
+BUILTIN(__builtin_ia32_loadups512_mask, "V16fvC*V16fUs", "")
+BUILTIN(__builtin_ia32_loadupd512_mask, "V8dvC*V8dUc", "")
+BUILTIN(__builtin_ia32_storedqudi512_mask, "vv*V8LLiUc", "")
+BUILTIN(__builtin_ia32_storedqusi512_mask, "vv*V16iUs", "")
+BUILTIN(__builtin_ia32_storeupd512_mask, "vv*V8dUc", "")
+BUILTIN(__builtin_ia32_storeups512_mask, "vv*V16fUs", "")
+BUILTIN(__builtin_ia32_vpermt2vard512_mask, "V16iV16iV16iV16iUs", "")
+BUILTIN(__builtin_ia32_vpermt2varq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "")
+BUILTIN(__builtin_ia32_vpermt2varps512_mask, "V16fV16iV16fV16fUs", "")
+BUILTIN(__builtin_ia32_vpermt2varpd512_mask, "V8dV8LLiV8dV8dUc", "")
+BUILTIN(__builtin_ia32_alignq512_mask, "V8LLiV8LLiV8LLiUcV8LLiUc", "")
+BUILTIN(__builtin_ia32_alignd512_mask, "V16iV16iV16iUcV16iUc", "")
+BUILTIN(__builtin_ia32_gathersiv8df, "V8dV8dvC*V8iUciC", "")
+BUILTIN(__builtin_ia32_gathersiv16sf, "V16fV16fvC*UsiC", "")
+BUILTIN(__builtin_ia32_gatherdiv8df, "V8dV8dvC*V8LLiUciC", "")
+BUILTIN(__builtin_ia32_gatherdiv16sf, "V8fV8fvC*V8LLiUciC", "")
+BUILTIN(__builtin_ia32_gathersiv8di, "V8LLiV8LLivC*V8iUciC", "")
+BUILTIN(__builtin_ia32_gathersiv16si, "V16iV16ivC*UsiC", "")
+BUILTIN(__builtin_ia32_gatherdiv8di, "V8LLiV8LLivC*V8LLiUciC", "")
+BUILTIN(__builtin_ia32_gatherdiv16si, "V8iV8ivC*V8LLiUciC", "")
+BUILTIN(__builtin_ia32_scattersiv8df, "vv*UcV8iV8diC", "")
+BUILTIN(__builtin_ia32_scattersiv16sf, "vv*UsV16iV16fiC", "")
+BUILTIN(__builtin_ia32_scatterdiv8df, "vv*UcV8LLiV8diC", "")
+BUILTIN(__builtin_ia32_scatterdiv16sf, "vv*UcV8LLiV8fiC", "")
+BUILTIN(__builtin_ia32_scattersiv8di, "vv*UcV8iV8LLiiC", "")
+BUILTIN(__builtin_ia32_scattersiv16si, "vv*UsV16iV16iiC", "")
+BUILTIN(__builtin_ia32_scatterdiv8di, "vv*UcV8LLiV8LLiiC", "")
+BUILTIN(__builtin_ia32_scatterdiv16si, "vv*UcV8LLiV8iiC", "")
+BUILTIN(__builtin_ia32_gatherpfdpd, "vUcV8ivC*iCiC", "")
+BUILTIN(__builtin_ia32_gatherpfdps, "vUsV16ivC*iCiC", "")
+BUILTIN(__builtin_ia32_gatherpfqpd, "vUcV8LLivC*iCiC", "")
+BUILTIN(__builtin_ia32_gatherpfqps, "vUcV8LLivC*iCiC", "")
+BUILTIN(__builtin_ia32_scatterpfdpd, "vUcV8iv*iCiC", "")
+BUILTIN(__builtin_ia32_scatterpfdps, "vUsV16iv*iCiC", "")
+BUILTIN(__builtin_ia32_scatterpfqpd, "vUcV8LLiv*iCiC", "")
+BUILTIN(__builtin_ia32_scatterpfqps, "vUcV8LLiv*iCiC", "")
+BUILTIN(__builtin_ia32_knothi, "UsUs", "")
+
#undef BUILTIN
diff --git a/include/clang/Basic/CharInfo.h b/include/clang/Basic/CharInfo.h
index d0afda43709a..dd9c55431e01 100644
--- a/include/clang/Basic/CharInfo.h
+++ b/include/clang/Basic/CharInfo.h
@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef CLANG_BASIC_CHARINFO_H
-#define CLANG_BASIC_CHARINFO_H
+#ifndef LLVM_CLANG_BASIC_CHARINFO_H
+#define LLVM_CLANG_BASIC_CHARINFO_H
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/StringRef.h"
diff --git a/include/clang/Basic/CommentOptions.h b/include/clang/Basic/CommentOptions.h
index 7991875838a4..92419f91b741 100644
--- a/include/clang/Basic/CommentOptions.h
+++ b/include/clang/Basic/CommentOptions.h
@@ -12,8 +12,8 @@
///
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_COMMENTOPTIONS_H
-#define LLVM_CLANG_COMMENTOPTIONS_H
+#ifndef LLVM_CLANG_BASIC_COMMENTOPTIONS_H
+#define LLVM_CLANG_BASIC_COMMENTOPTIONS_H
#include <string>
#include <vector>
diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h
index a7b2ba270d46..91e94db802b1 100644
--- a/include/clang/Basic/Diagnostic.h
+++ b/include/clang/Basic/Diagnostic.h
@@ -12,8 +12,8 @@
///
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_DIAGNOSTIC_H
-#define LLVM_CLANG_DIAGNOSTIC_H
+#ifndef LLVM_CLANG_BASIC_DIAGNOSTIC_H
+#define LLVM_CLANG_BASIC_DIAGNOSTIC_H
#include "clang/Basic/DiagnosticIDs.h"
#include "clang/Basic/DiagnosticOptions.h"
@@ -187,7 +187,7 @@ private:
IntrusiveRefCntPtr<DiagnosticIDs> Diags;
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
DiagnosticConsumer *Client;
- bool OwnsDiagClient;
+ std::unique_ptr<DiagnosticConsumer> Owner;
SourceManager *SourceMgr;
/// \brief Mapping information for diagnostics.
@@ -302,7 +302,6 @@ private:
unsigned NumWarnings; ///< Number of warnings reported
unsigned NumErrors; ///< Number of errors reported
- unsigned NumErrorsSuppressed; ///< Number of errors suppressed
/// \brief A function pointer that converts an opaque diagnostic
/// argument to a strings.
@@ -369,14 +368,11 @@ public:
const DiagnosticConsumer *getClient() const { return Client; }
/// \brief Determine whether this \c DiagnosticsEngine object own its client.
- bool ownsClient() const { return OwnsDiagClient; }
-
+ bool ownsClient() const { return Owner != nullptr; }
+
/// \brief Return the current diagnostic client along with ownership of that
/// client.
- DiagnosticConsumer *takeClient() {
- OwnsDiagClient = false;
- return Client;
- }
+ std::unique_ptr<DiagnosticConsumer> takeClient() { return std::move(Owner); }
bool hasSourceManager() const { return SourceMgr != nullptr; }
SourceManager &getSourceManager() const {
diff --git a/include/clang/Basic/DiagnosticASTKinds.td b/include/clang/Basic/DiagnosticASTKinds.td
index 8d5a1c77233b..d353b451aaa7 100644
--- a/include/clang/Basic/DiagnosticASTKinds.td
+++ b/include/clang/Basic/DiagnosticASTKinds.td
@@ -141,6 +141,13 @@ def note_constexpr_calls_suppressed : Note<
"(skipping %0 call%s0 in backtrace; use -fconstexpr-backtrace-limit=0 to "
"see all)">;
def note_constexpr_call_here : Note<"in call to '%0'">;
+def note_constexpr_baa_insufficient_alignment : Note<
+ "%select{alignment of|offset of the aligned pointer from}0 the base pointee "
+ "object (%1 %plural{1:byte|:bytes}1) is %select{less than|not a multiple of}0 the "
+ "asserted %2 %plural{1:byte|:bytes}2">;
+def note_constexpr_baa_value_insufficient_alignment : Note<
+ "value of the aligned pointer (%0) is not a multiple of the asserted %1 "
+ "%plural{1:byte|:bytes}1">;
def warn_integer_constant_overflow : Warning<
"overflow in expression; result is %0 with type %1">,
diff --git a/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td
index b3c77b8f5f36..ff9ed69022ec 100644
--- a/include/clang/Basic/DiagnosticCommonKinds.td
+++ b/include/clang/Basic/DiagnosticCommonKinds.td
@@ -81,6 +81,8 @@ def err_deleted_non_function : Error<
"only functions can have deleted definitions">;
def err_module_not_found : Error<"module '%0' not found">, DefaultFatal;
def err_module_not_built : Error<"could not build module '%0'">, DefaultFatal;
+def err_module_lock_failure : Error<
+ "could not acquire lock file for module '%0'">, DefaultFatal;
def err_module_cycle : Error<"cyclic dependency in module '%0': %1">,
DefaultFatal;
def note_pragma_entered_here : Note<"#pragma entered here">;
@@ -102,10 +104,12 @@ def ext_cxx11_longlong : Extension<
def warn_cxx98_compat_longlong : Warning<
"'long long' is incompatible with C++98">,
InGroup<CXX98CompatPedantic>, DefaultIgnore;
-def err_integer_too_large : Error<
- "integer constant is larger than the largest unsigned integer type">;
-def ext_integer_too_large_for_signed : ExtWarn<
- "integer constant is larger than the largest signed integer type">,
+def err_integer_literal_too_large : Error<
+ "integer literal is too large to be represented in any %select{signed |}0"
+ "integer type">;
+def ext_integer_literal_too_large_for_signed : ExtWarn<
+ "integer literal is too large to be represented in a signed integer type, "
+ "interpreting as unsigned">,
InGroup<DiagGroup<"implicitly-unsigned-literal">>;
// Sema && AST
@@ -121,6 +125,8 @@ def err_target_unknown_abi : Error<"unknown target ABI '%0'">;
def err_target_unknown_fpmath : Error<"unknown FP unit '%0'">;
def err_target_unsupported_fpmath : Error<
"the '%0' unit is not supported with this instruction set">;
+def err_target_unsupported_unaligned : Error<
+ "the %0 sub-architecture does not support unaligned accesses">;
// Source manager
def err_cannot_open_file : Error<"cannot open file '%0': %1">, DefaultFatal;
diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td
index cd26a6a4dd70..41c78ee669dc 100644
--- a/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/include/clang/Basic/DiagnosticDriverKinds.td
@@ -22,6 +22,8 @@ def err_drv_unknown_stdin_type_clang_cl : Error<
def err_drv_unknown_language : Error<"language not recognized: '%0'">;
def err_drv_invalid_arch_name : Error<
"invalid arch name '%0'">;
+def err_drv_invalid_thread_model_for_target : Error<
+ "invalid thread model '%0' in '%1' for this target">;
def err_drv_invalid_linker_name : Error<
"invalid linker name in argument '%0'">;
def err_drv_invalid_rtlib_name : Error<
@@ -100,10 +102,6 @@ def err_drv_cc_print_options_failure : Error<
"unable to open CC_PRINT_OPTIONS file: %0">;
def err_drv_preamble_format : Error<
"incorrect format for -preamble-bytes=N,END">;
-def err_drv_conflicting_deployment_targets : Error<
- "conflicting deployment targets, both '%0' and '%1' are present in environment">;
-def err_drv_invalid_arch_for_deployment_target : Error<
- "invalid architecture '%0' for deployment target '%1'">;
def err_drv_objc_gc_arr : Error<
"cannot specify both '-fobjc-arc' and '%0'">;
def err_arc_unsupported_on_runtime : Error<
@@ -124,7 +122,7 @@ def warn_O4_is_O3 : Warning<"-O4 is equivalent to -O3">, InGroup<Deprecated>;
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>;
+ InGroup<IgnoredOptimizationArgument>;
def warn_c_kext : Warning<
"ignoring -fapple-kext which is valid for C++ and Objective-C++ only">;
def warn_drv_input_file_unused : Warning<
@@ -165,9 +163,11 @@ def warn_debug_compression_unavailable : Warning<"cannot compress debug sections
def note_drv_command_failed_diag_msg : Note<
"diagnostic msg: %0">;
-def note_drv_t_option_is_global :
- Note<"The last /TC or /TP option takes precedence over earlier instances">;
-
+def note_drv_t_option_is_global : Note<
+ "The last /TC or /TP option takes precedence over earlier instances">;
+def note_drv_address_sanitizer_debug_runtime : Note<
+ "AddressSanitizer doesn't support linking with debug runtime libraries yet">;
+
def err_analyzer_config_no_value : Error<
"analyzer-config option '%0' has a key but no value">;
def err_analyzer_config_multiple_values : Error<
@@ -175,7 +175,7 @@ def err_analyzer_config_multiple_values : Error<
def err_drv_modules_validate_once_requires_timestamp : Error<
"option '-fmodules-validate-once-per-build-session' requires "
- "'-fbuild-session-timestamp=<seconds since Epoch>'">;
+ "'-fbuild-session-timestamp=<seconds since Epoch>' or '-fbuild-session-file=<file>'">;
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 ae704c49150b..15f74b11698f 100644
--- a/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -46,6 +46,16 @@ def warn_fe_backend_optimization_failure : Warning<"%0">, BackendInfo,
def note_fe_backend_optimization_remark_invalid_loc : Note<"could "
"not determine the original source location for %0:%1:%2">;
+def remark_sanitize_address_insert_extra_padding_accepted : Remark<
+ "-fsanitize-address-field-padding applied to %0">, ShowInSystemHeader,
+ InGroup<SanitizeAddressRemarks>;
+def remark_sanitize_address_insert_extra_padding_rejected : Remark<
+ "-fsanitize-address-field-padding ignored for %0 because it "
+ "%select{is not C++|is packed|is a union|is trivially copyable|"
+ "has trivial destructor|is standard layout|is in a blacklisted file|"
+ "is blacklisted}1">, ShowInSystemHeader,
+ InGroup<SanitizeAddressRemarks>;
+
def err_fe_invalid_code_complete_file : Error<
"cannot locate code-completion file %0">, DefaultFatal;
def err_fe_stdout_binary : Error<"unable to change standard output to binary">,
@@ -85,9 +95,12 @@ def err_fe_no_pch_in_dir : Error<
def err_fe_action_not_available : Error<
"action %0 not compiled in">;
+def warn_fe_serialized_diag_merge_failure : Warning<
+ "unable to merge a subprocess's serialized diagnostics">,
+ InGroup<SerializedDiagnostics>;
def warn_fe_serialized_diag_failure : Warning<
"unable to open file %0 for serializing diagnostics (%1)">,
- InGroup<DiagGroup<"serialized-diagnostics">>;
+ InGroup<SerializedDiagnostics>;
def err_verify_missing_line : Error<
"missing or invalid line number following '@' in expected %0">;
@@ -135,12 +148,15 @@ def warn_unknown_warning_specifier : Warning<
def err_unknown_analyzer_checker : Error<
"no analyzer checkers are associated with '%0'">;
+def note_suggest_disabling_all_checkers : Note<
+ "use -analyzer-disable-all-checks to disable all static analyzer checkers">;
+
def warn_incompatible_analyzer_plugin_api : Warning<
"checker plugin '%0' is not compatible with this version of the analyzer">,
InGroup<DiagGroup<"analyzer-incompatible-plugin"> >;
def note_incompatible_analyzer_plugin_api : Note<
"current API version is '%0', but plugin was compiled with version '%1'">;
-
+
def err_module_map_not_found : Error<"module map file '%0' not found">,
DefaultFatal;
def err_missing_module_name : Error<
@@ -167,7 +183,19 @@ def warn_module_config_macro_undef : Warning<
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">>;
+ InGroup<ModuleBuild>;
+def remark_module_build_done : Remark<"finished building module '%0'">,
+ InGroup<ModuleBuild>;
+
+def err_conflicting_module_names : Error<
+ "conflicting module names specified: '-fmodule-name=%0' and "
+ "'-fmodule-implementation-of %1'">;
+def err_conflicting_module_files : Error<
+ "module '%0' is defined in both '%1' and '%2'">;
+def err_module_file_not_found : Error<
+ "file '%0' is not a precompiled module file">, DefaultFatal;
+def err_module_file_not_module : Error<
+ "AST file '%0' was not built as a module">, DefaultFatal;
def err_missing_vfs_overlay_file : Error<
"virtual filesystem overlay file '%0' not found">, DefaultFatal;
diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td
index 58dee482b627..75d40b17a67c 100644
--- a/include/clang/Basic/DiagnosticGroups.td
+++ b/include/clang/Basic/DiagnosticGroups.td
@@ -60,7 +60,7 @@ def ExternCCompat : DiagGroup<"extern-c-compat">;
def KeywordCompat : DiagGroup<"keyword-compat">;
def GNUCaseRange : DiagGroup<"gnu-case-range">;
def CastAlign : DiagGroup<"cast-align">;
-def : DiagGroup<"cast-qual">;
+def CastQual : DiagGroup<"cast-qual">;
def : DiagGroup<"char-align">;
def Comment : DiagGroup<"comment">;
def GNUComplexInteger : DiagGroup<"gnu-complex-integer">;
@@ -71,6 +71,7 @@ def GNUDesignator : DiagGroup<"gnu-designator">;
def GNUStringLiteralOperatorTemplate :
DiagGroup<"gnu-string-literal-operator-template">;
+def DeleteIncomplete : DiagGroup<"delete-incomplete">;
def DeleteNonVirtualDtor : DiagGroup<"delete-non-virtual-dtor">;
def AbstractFinalClass : DiagGroup<"abstract-final-class">;
@@ -118,9 +119,9 @@ def FormatExtraArgs : DiagGroup<"format-extra-args">;
def FormatZeroLength : DiagGroup<"format-zero-length">;
// Warnings for C++1y code which is not compatible with prior C++ standards.
-def CXXPre1yCompat : DiagGroup<"c++98-c++11-compat">;
-def CXXPre1yCompatPedantic : DiagGroup<"c++98-c++11-compat-pedantic",
- [CXXPre1yCompat]>;
+def CXXPre14Compat : DiagGroup<"c++98-c++11-compat">;
+def CXXPre14CompatPedantic : DiagGroup<"c++98-c++11-compat-pedantic",
+ [CXXPre14Compat]>;
def CXXPre1zCompat : DiagGroup<"c++98-c++11-c++14-compat">;
def CXXPre1zCompatPedantic : DiagGroup<"c++98-c++11-c++14-compat-pedantic",
[CXXPre1zCompat]>;
@@ -133,19 +134,21 @@ def CXX98CompatUnnamedTypeTemplateArgs :
DiagGroup<"c++98-compat-unnamed-type-template-args">;
def CXX98Compat : DiagGroup<"c++98-compat",
- [CXX98CompatBindToTemporaryCopy,
- CXX98CompatLocalTypeTemplateArgs,
+ [CXX98CompatLocalTypeTemplateArgs,
CXX98CompatUnnamedTypeTemplateArgs,
- CXXPre1yCompat,
+ CXXPre14Compat,
CXXPre1zCompat]>;
// Warnings for C++11 features which are Extensions in C++98 mode.
def CXX98CompatPedantic : DiagGroup<"c++98-compat-pedantic",
[CXX98Compat,
- CXXPre1yCompatPedantic,
+ CXX98CompatBindToTemporaryCopy,
+ CXXPre14CompatPedantic,
CXXPre1zCompatPedantic]>;
def CXX11Narrowing : DiagGroup<"c++11-narrowing">;
+def CXX11WarnOverrideMethod : DiagGroup<"inconsistent-missing-override">;
+
// Original name of this warning in Clang
def : DiagGroup<"c++0x-narrowing", [CXX11Narrowing]>;
@@ -162,11 +165,11 @@ def CXX11Compat : DiagGroup<"c++11-compat",
[CXX11Narrowing,
CXX11CompatReservedUserDefinedLiteral,
CXX11CompatDeprecatedWritableStr,
- CXXPre1yCompat,
+ CXXPre14Compat,
CXXPre1zCompat]>;
def : DiagGroup<"c++0x-compat", [CXX11Compat]>;
def CXX11CompatPedantic : DiagGroup<"c++11-compat-pedantic",
- [CXXPre1yCompatPedantic,
+ [CXXPre14CompatPedantic,
CXXPre1zCompatPedantic]>;
def CXX14Compat : DiagGroup<"c++14-compat", [CXXPre1zCompat]>;
@@ -187,6 +190,7 @@ def OverloadedShiftOpParentheses: DiagGroup<"overloaded-shift-op-parentheses">;
def DanglingElse: DiagGroup<"dangling-else">;
def DanglingField : DiagGroup<"dangling-field">;
def DistributedObjectModifiers : DiagGroup<"distributed-object-modifiers">;
+def FlagEnum : DiagGroup<"flag-enum">;
def InfiniteRecursion : DiagGroup<"infinite-recursion">;
def GNUImaginaryConstant : DiagGroup<"gnu-imaginary-constant">;
def IgnoredQualifiers : DiagGroup<"ignored-qualifiers">;
@@ -198,11 +202,13 @@ def IncompatiblePointerTypes
: DiagGroup<"incompatible-pointer-types",
[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 IncompleteModule : DiagGroup<"incomplete-module",
+ [IncompleteUmbrella, NonModularIncludeInModule]>;
+
def InvalidNoreturn : DiagGroup<"invalid-noreturn">;
def InvalidSourceEncoding : DiagGroup<"invalid-source-encoding">;
def KNRPromotedParameter : DiagGroup<"knr-promoted-parameter">;
@@ -231,6 +237,7 @@ def MismatchedParameterTypes : DiagGroup<"mismatched-parameter-types">;
def MismatchedReturnTypes : DiagGroup<"mismatched-return-types">;
def MismatchedTags : DiagGroup<"mismatched-tags">;
def MissingFieldInitializers : DiagGroup<"missing-field-initializers">;
+def ModuleBuild : DiagGroup<"module-build">;
def ModuleConflict : DiagGroup<"module-conflict">;
def NewlineEOF : DiagGroup<"newline-eof">;
def NullArithmetic : DiagGroup<"null-arithmetic">;
@@ -267,7 +274,9 @@ def ObjCInvalidIBOutletProperty : DiagGroup<"invalid-iboutlet">;
def ObjCRootClass : DiagGroup<"objc-root-class">;
def ObjCPointerIntrospectPerformSelector : DiagGroup<"deprecated-objc-pointer-introspection-performSelector">;
def ObjCPointerIntrospect : DiagGroup<"deprecated-objc-pointer-introspection", [ObjCPointerIntrospectPerformSelector]>;
+def ObjCMultipleMethodNames : DiagGroup<"objc-multiple-method-names">;
def DeprecatedObjCIsaUsage : DiagGroup<"deprecated-objc-isa-usage">;
+def ExplicitInitializeCall : DiagGroup<"explicit-initialize-call">;
def Packed : DiagGroup<"packed">;
def Padded : DiagGroup<"padded">;
def PointerArith : DiagGroup<"pointer-arith">;
@@ -285,6 +294,7 @@ def BindToTemporaryCopy : DiagGroup<"bind-to-temporary-copy",
[CXX98CompatBindToTemporaryCopy]>;
def SelfAssignmentField : DiagGroup<"self-assign-field">;
def SelfAssignment : DiagGroup<"self-assign", [SelfAssignmentField]>;
+def SelfMove : DiagGroup<"self-move">;
def SemiBeforeMethodBody : DiagGroup<"semicolon-before-method-body">;
def Sentinel : DiagGroup<"sentinel">;
def MissingMethodReturnType : DiagGroup<"missing-method-return-type">;
@@ -329,6 +339,8 @@ def : DiagGroup<"sequence-point", [Unsequenced]>;
// Preprocessor warnings.
def AmbiguousMacro : DiagGroup<"ambiguous-macro">;
+def KeywordAsMacro : DiagGroup<"keyword-macro">;
+def ReservedIdAsMacro : DiagGroup<"reserved-id-macro">;
// Just silence warnings about -Wstrict-aliasing for now.
def : DiagGroup<"strict-aliasing=0">;
@@ -349,6 +361,7 @@ def InvalidOffsetof : DiagGroup<"invalid-offsetof">;
def : DiagGroup<"strict-prototypes">;
def StrictSelector : DiagGroup<"strict-selector-match">;
def MethodDuplicate : DiagGroup<"duplicate-method-match">;
+def ObjCCStringFormat : DiagGroup<"cstring-format-directive">;
def CoveredSwitchDefault : DiagGroup<"covered-switch-default">;
def SwitchBool : DiagGroup<"switch-bool">;
def SwitchEnum : DiagGroup<"switch-enum">;
@@ -383,7 +396,9 @@ def UnnamedTypeTemplateArgs : DiagGroup<"unnamed-type-template-args",
def UnsupportedFriend : DiagGroup<"unsupported-friend">;
def UnusedArgument : DiagGroup<"unused-argument">;
def UnusedCommandLineArgument : DiagGroup<"unused-command-line-argument">;
-def InvalidCommandLineArgument : DiagGroup<"invalid-command-line-argument">;
+def IgnoredOptimizationArgument : DiagGroup<"ignored-optimization-argument">;
+def InvalidCommandLineArgument : DiagGroup<"invalid-command-line-argument",
+ [IgnoredOptimizationArgument]>;
def UnusedComparison : DiagGroup<"unused-comparison">;
def UnusedExceptionParameter : DiagGroup<"unused-exception-parameter">;
def UnneededInternalDecl : DiagGroup<"unneeded-internal-declaration">;
@@ -395,11 +410,17 @@ def UnusedMemberFunction : DiagGroup<"unused-member-function",
def UnusedLabel : DiagGroup<"unused-label">;
def UnusedParameter : DiagGroup<"unused-parameter">;
def UnusedResult : DiagGroup<"unused-result">;
-def UnusedValue : DiagGroup<"unused-value", [UnusedComparison, UnusedResult]>;
+def PotentiallyEvaluatedExpression : DiagGroup<"potentially-evaluated-expression">;
+def UnevaluatedExpression : DiagGroup<"unevaluated-expression",
+ [PotentiallyEvaluatedExpression]>;
+def UnusedValue : DiagGroup<"unused-value", [UnusedComparison, UnusedResult,
+ UnevaluatedExpression]>;
def UnusedConstVariable : DiagGroup<"unused-const-variable">;
def UnusedVariable : DiagGroup<"unused-variable",
[UnusedConstVariable]>;
+def UnusedLocalTypedef : DiagGroup<"unused-local-typedef">;
def UnusedPropertyIvar : DiagGroup<"unused-property-ivar">;
+def UnusedGetterReturnValue : DiagGroup<"unused-getter-return-value">;
def UsedButMarkedUnused : DiagGroup<"used-but-marked-unused">;
def UserDefinedLiterals : DiagGroup<"user-defined-literals">;
def Reorder : DiagGroup<"reorder">;
@@ -408,8 +429,6 @@ def ImplicitAtomic : DiagGroup<"implicit-atomic-properties">;
def CustomAtomic : DiagGroup<"custom-atomic-properties">;
def AtomicProperties : DiagGroup<"atomic-properties",
[ImplicitAtomic, CustomAtomic]>;
-// FIXME: Remove arc-abi once an Xcode is released that doesn't pass this flag.
-def : DiagGroup<"arc-abi">;
def ARCUnsafeRetainedAssign : DiagGroup<"arc-unsafe-retained-assign">;
def ARCRetainCycles : DiagGroup<"arc-retain-cycles">;
def ARCNonPodMemAccess : DiagGroup<"arc-non-pod-memaccess">;
@@ -426,6 +445,9 @@ def DeallocInCategory:DiagGroup<"dealloc-in-category">;
def SelectorTypeMismatch : DiagGroup<"selector-type-mismatch">;
def Selector : DiagGroup<"selector", [SelectorTypeMismatch]>;
def Protocol : DiagGroup<"protocol">;
+def AtProtocol : DiagGroup<"at-protocol">;
+def PropertyAccessDotSyntax: DiagGroup<"property-access-dot-syntax">;
+def PropertyAttr : DiagGroup<"property-attribute-mismatch">;
def SuperSubClassMismatch : DiagGroup<"super-class-method-mismatch">;
def OverridingMethodMismatch : DiagGroup<"overriding-method-mismatch">;
def VariadicMacros : DiagGroup<"variadic-macros">;
@@ -520,7 +542,7 @@ def Unused : DiagGroup<"unused",
[UnusedArgument, UnusedFunction, UnusedLabel,
// UnusedParameter, (matches GCC's behavior)
// UnusedMemberFunction, (clean-up llvm before enabling)
- UnusedPrivateField,
+ UnusedPrivateField, UnusedLocalTypedef,
UnusedValue, UnusedVariable, UnusedPropertyIvar]>,
DiagCategory<"Unused Entity Issue">;
@@ -565,6 +587,7 @@ def Most : DiagGroup<"most", [
Reorder,
ReturnType,
SelfAssignment,
+ SelfMove,
SizeofArrayArgument,
SizeofArrayDecay,
StringPlusInt,
@@ -585,10 +608,14 @@ def Most : DiagGroup<"most", [
def ThreadSafetyAttributes : DiagGroup<"thread-safety-attributes">;
def ThreadSafetyAnalysis : DiagGroup<"thread-safety-analysis">;
def ThreadSafetyPrecise : DiagGroup<"thread-safety-precise">;
+def ThreadSafetyReference : DiagGroup<"thread-safety-reference">;
+def ThreadSafetyNegative : DiagGroup<"thread-safety-negative">;
def ThreadSafety : DiagGroup<"thread-safety",
[ThreadSafetyAttributes,
ThreadSafetyAnalysis,
- ThreadSafetyPrecise]>;
+ ThreadSafetyPrecise,
+ ThreadSafetyReference]>;
+def ThreadSafetyVerbose : DiagGroup<"thread-safety-verbose">;
def ThreadSafetyBeta : DiagGroup<"thread-safety-beta">;
// Uniqueness Analysis warnings
@@ -614,6 +641,8 @@ def : DiagGroup<"int-conversions",
[IntConversion]>; // -Wint-conversions = -Wint-conversion
def : DiagGroup<"vector-conversions",
[VectorConversion]>; // -Wvector-conversions = -Wvector-conversion
+def : DiagGroup<"unused-local-typedefs", [UnusedLocalTypedef]>;
+ // -Wunused-local-typedefs = -Wunused-local-typedef
// A warning group for warnings that we want to have on by default in clang,
// but which aren't on by default in GCC.
@@ -624,15 +653,17 @@ def NonGCC : DiagGroup<"non-gcc",
// earlier C++ versions.
def CXX11 : DiagGroup<"c++11-extensions", [CXX11ExtraSemi, CXX11LongLong]>;
-// A warning group for warnings about using C++1y features as extensions in
+// A warning group for warnings about using C++14 features as extensions in
// earlier C++ versions.
-def CXX1y : DiagGroup<"c++1y-extensions">;
+def CXX14 : DiagGroup<"c++14-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 : DiagGroup<"c++1y-extensions", [CXX14]>;
+
def DelegatingCtorCycles :
DiagGroup<"delegating-ctor-cycles">;
@@ -710,6 +741,12 @@ def BackendOptimizationFailure : DiagGroup<"pass-failed">;
def ProfileInstrOutOfDate : DiagGroup<"profile-instr-out-of-date">;
def ProfileInstrUnprofiled : DiagGroup<"profile-instr-unprofiled">;
+// AddressSanitizer frontent instrumentation remarks.
+def SanitizeAddressRemarks : DiagGroup<"sanitize-address">;
+
+// Issues with serialized diagnostics.
+def SerializedDiagnostics : DiagGroup<"serialized-diagnostics">;
+
// A warning group for warnings about code that clang accepts when
// compiling CUDA C/C++ but which is not compatible with the CUDA spec.
def CudaCompat : DiagGroup<"cuda-compat">;
diff --git a/include/clang/Basic/DiagnosticIDs.h b/include/clang/Basic/DiagnosticIDs.h
index bfb0f0d1ee5d..99b469d70e78 100644
--- a/include/clang/Basic/DiagnosticIDs.h
+++ b/include/clang/Basic/DiagnosticIDs.h
@@ -12,8 +12,8 @@
///
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_DIAGNOSTICIDS_H
-#define LLVM_CLANG_DIAGNOSTICIDS_H
+#ifndef LLVM_CLANG_BASIC_DIAGNOSTICIDS_H
+#define LLVM_CLANG_BASIC_DIAGNOSTICIDS_H
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
@@ -33,7 +33,7 @@ namespace clang {
DIAG_START_SERIALIZATION = DIAG_START_FRONTEND + 100,
DIAG_START_LEX = DIAG_START_SERIALIZATION + 120,
DIAG_START_PARSE = DIAG_START_LEX + 300,
- DIAG_START_AST = DIAG_START_PARSE + 400,
+ DIAG_START_AST = DIAG_START_PARSE + 500,
DIAG_START_COMMENT = DIAG_START_AST + 100,
DIAG_START_SEMA = DIAG_START_COMMENT + 100,
DIAG_START_ANALYSIS = DIAG_START_SEMA + 3000,
diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td
index 86def878834f..93cc7c297813 100644
--- a/include/clang/Basic/DiagnosticLexKinds.td
+++ b/include/clang/Basic/DiagnosticLexKinds.td
@@ -161,8 +161,8 @@ def err_invalid_suffix_integer_constant : Error<
def err_invalid_suffix_float_constant : Error<
"invalid suffix '%0' on floating constant">;
def warn_cxx11_compat_digit_separator : Warning<
- "digit separators are incompatible with C++ standards before C++1y">,
- InGroup<CXXPre1yCompat>, DefaultIgnore;
+ "digit separators are incompatible with C++ standards before C++14">,
+ InGroup<CXXPre14Compat>, DefaultIgnore;
def err_digit_separator_not_between_digits : Error<
"digit separator cannot appear at %select{start|end}0 of digit sequence">;
def warn_extraneous_char_constant : Warning<
@@ -182,11 +182,11 @@ def ext_hexconstant_invalid : Extension<
"hexadecimal floating constants are a C99 feature">, InGroup<C99>;
def ext_binary_literal : Extension<
"binary integer literals are a GNU extension">, InGroup<GNUBinaryLiteral>;
-def ext_binary_literal_cxx1y : Extension<
- "binary integer literals are a C++1y extension">, InGroup<CXX1y>;
+def ext_binary_literal_cxx14 : Extension<
+ "binary integer literals are a C++14 extension">, InGroup<CXX14>;
def warn_cxx11_compat_binary_literal : Warning<
- "binary integer literals are incompatible with C++ standards before C++1y">,
- InGroup<CXXPre1yCompatPedantic>, DefaultIgnore;
+ "binary integer literals are incompatible with C++ standards before C++14">,
+ InGroup<CXXPre14CompatPedantic>, DefaultIgnore;
def err_pascal_string_too_long : Error<"Pascal string is too long">;
def err_octal_escape_too_large : Error<"octal escape sequence out of range">;
def err_hex_escape_too_large : Error<"hex escape sequence out of range">;
@@ -201,6 +201,9 @@ def warn_c99_compat_unicode_literal : Warning<
def warn_cxx98_compat_unicode_literal : Warning<
"unicode literals are incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
+def warn_cxx14_compat_u8_character_literal : Warning<
+ "unicode literals are incompatible with C++ standards before C++1z">,
+ InGroup<CXXPre1zCompat>, DefaultIgnore;
def warn_cxx11_compat_user_defined_literal : Warning<
"identifier after literal will be treated as a user-defined literal suffix "
"in C++11">, InGroup<CXX11Compat>, DefaultIgnore;
@@ -287,6 +290,11 @@ def note_pp_ambiguous_macro_chosen : Note<
"expanding this definition of %0">;
def note_pp_ambiguous_macro_other : Note<
"other definition of %0">;
+def warn_pp_macro_hides_keyword : Extension<
+ "keyword is hidden by macro definition">, InGroup<KeywordAsMacro>;
+def warn_pp_macro_is_reserved_id : Warning<
+ "macro name is a reserved identifier">, DefaultIgnore,
+ InGroup<ReservedIdAsMacro>;
def pp_invalid_string_literal : Warning<
"invalid string literal, ignoring final '\\'">;
@@ -324,7 +332,7 @@ def warn_cxx98_compat_variadic_macro : Warning<
InGroup<CXX98CompatPedantic>, DefaultIgnore;
def ext_named_variadic_macro : Extension<
"named variadic macros are a GNU extension">, InGroup<VariadicMacros>;
-def err_embedded_include : Error<
+def err_embedded_directive : Error<
"embedding a #%0 directive within macro arguments is not supported">;
def ext_embedded_directive : Extension<
"embedding a directive within macro arguments has undefined behavior">,
@@ -615,9 +623,6 @@ def warn_auto_module_import : Warning<
def warn_uncovered_module_header : Warning<
"umbrella header for module '%0' does not include header '%1'">,
InGroup<IncompleteUmbrella>;
-def warn_forgotten_module_header : Warning<
- "header '%0' is included in module '%1' but not listed in module map">,
- InGroup<IncompleteModule>, DefaultIgnore;
def err_expected_id_building_module : Error<
"expected a module name in '__building_module' expression">;
def error_use_of_private_header_outside_module : Error<
diff --git a/include/clang/Basic/DiagnosticOptions.def b/include/clang/Basic/DiagnosticOptions.def
index a360a5a84e98..fdd325446e27 100644
--- a/include/clang/Basic/DiagnosticOptions.def
+++ b/include/clang/Basic/DiagnosticOptions.def
@@ -81,6 +81,8 @@ VALUE_DIAGOPT(MacroBacktraceLimit, 32, DefaultMacroBacktraceLimit)
VALUE_DIAGOPT(TemplateBacktraceLimit, 32, DefaultTemplateBacktraceLimit)
/// Limit depth of constexpr backtrace.
VALUE_DIAGOPT(ConstexprBacktraceLimit, 32, DefaultConstexprBacktraceLimit)
+/// Limit number of times to perform spell checking.
+VALUE_DIAGOPT(SpellCheckingLimit, 32, DefaultSpellCheckingLimit)
VALUE_DIAGOPT(TabStop, 32, DefaultTabStop) /// The distance between tab stops.
/// Column limit for formatting message diagnostics, or 0 if unused.
@@ -92,4 +94,3 @@ VALUE_DIAGOPT(MessageLength, 32, 0)
#undef SEMANTIC_DIAGOPT
#undef SEMANTIC_ENUM_DIAGOPT
#undef SEMANTIC_VALUE_DIAGOPT
-
diff --git a/include/clang/Basic/DiagnosticOptions.h b/include/clang/Basic/DiagnosticOptions.h
index 3e4d0eefbcf9..058e00f73e77 100644
--- a/include/clang/Basic/DiagnosticOptions.h
+++ b/include/clang/Basic/DiagnosticOptions.h
@@ -33,7 +33,8 @@ public:
enum { DefaultTabStop = 8, MaxTabStop = 100,
DefaultMacroBacktraceLimit = 6,
DefaultTemplateBacktraceLimit = 10,
- DefaultConstexprBacktraceLimit = 10 };
+ DefaultConstexprBacktraceLimit = 10,
+ DefaultSpellCheckingLimit = 50 };
// Define simple diagnostic options (with no accessors).
#define DIAGOPT(Name, Bits, Default) unsigned Name : Bits;
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index b1305e182f0b..239d4d20bb72 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -108,6 +108,9 @@ def ext_alignof_expr : ExtWarn<
def warn_microsoft_dependent_exists : Warning<
"dependent %select{__if_not_exists|__if_exists}0 declarations are ignored">,
InGroup<DiagGroup<"microsoft-exists">>;
+def warn_microsoft_qualifiers_ignored : Warning<
+ "qualifiers after comma in declarator list are ignored">,
+ InGroup<IgnoredAttributes>;
def ext_c11_generic_selection : Extension<
"generic selections are a C11-specific feature">, InGroup<C11>;
@@ -121,11 +124,15 @@ def ext_c11_alignment : Extension<
def ext_c11_noreturn : Extension<
"_Noreturn functions are a C11-specific feature">, InGroup<C11>;
+def err_c11_noreturn_misplaced : Error<
+ "'_Noreturn' keyword must precede function declarator">;
def ext_gnu_indirect_goto : Extension<
"use of GNU indirect-goto extension">, InGroup<GNULabelsAsValue>;
def ext_gnu_address_of_label : Extension<
"use of GNU address-of-label extension">, InGroup<GNULabelsAsValue>;
+def err_stmtexpr_file_scope : Error<
+ "statement expression not allowed at file scope">;
def ext_gnu_statement_expr : Extension<
"use of GNU statement expression extension">, InGroup<GNUStatementExpression>;
def ext_gnu_conditional_expr : Extension<
@@ -167,6 +174,9 @@ def err_expected_fn_body : Error<
def warn_attribute_on_function_definition : Warning<
"GCC does not allow %0 attribute in this position on a function definition">,
InGroup<GccCompat>;
+def warn_gcc_attribute_location : Warning<
+ "GCC does not allow an attribute in this position on a function declaration">,
+ InGroup<GccCompat>;
def warn_attribute_no_decl : Warning<
"attribute %0 ignored, because it is not attached to a declaration">,
InGroup<IgnoredAttributes>;
@@ -194,11 +204,19 @@ def err_expected_semi_after_namespace_name : Error<
"expected ';' after namespace name">;
def err_unexpected_namespace_attributes_alias : Error<
"attributes cannot be specified on namespace alias">;
+def err_unexpected_nested_namespace_attribute : Error<
+ "attributes cannot be specified on a nested namespace definition">;
def err_inline_namespace_alias : Error<"namespace alias cannot be inline">;
def err_namespace_nonnamespace_scope : Error<
"namespaces can only be defined in global or namespace scope">;
-def err_nested_namespaces_with_double_colon : Error<
- "nested namespace definition must define each namespace separately">;
+def ext_nested_namespace_definition : ExtWarn<
+ "nested namespace definition is a C++1z extension; "
+ "define each namespace separately">, InGroup<CXX1z>;
+def warn_cxx14_compat_nested_namespace_definition : Warning<
+ "nested namespace definition is incompatible with C++ standards before C++1z">,
+ InGroup<CXXPre1zCompat>, DefaultIgnore;
+def err_inline_nested_namespace_definition : Error<
+ "nested namespace definition cannot be 'inline'">;
def err_expected_semi_after_attribute_list : Error<
"expected ';' after attribute list">;
def err_expected_semi_after_static_assert : Error<
@@ -268,22 +286,17 @@ def ext_auto_storage_class : ExtWarn<
"'auto' storage class specifier is not permitted in C++11, and will not "
"be supported in future releases">, InGroup<DiagGroup<"auto-storage-class">>;
def ext_decltype_auto_type_specifier : ExtWarn<
- "'decltype(auto)' type specifier is a C++1y extension">, InGroup<CXX1y>;
+ "'decltype(auto)' type specifier is a C++14 extension">, InGroup<CXX14>;
def warn_cxx11_compat_decltype_auto_type_specifier : Warning<
"'decltype(auto)' type specifier is incompatible with C++ standards before "
- "C++1y">, InGroup<CXXPre1yCompat>, DefaultIgnore;
+ "C++14">, InGroup<CXXPre14Compat>, DefaultIgnore;
def ext_for_range : ExtWarn<
"range-based for loop is a C++11 extension">, InGroup<CXX11>;
def warn_cxx98_compat_for_range : Warning<
"range-based for loop is incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
-def 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_identifier : Error<
+ "range-based for loop requires type for loop variable">;
def err_for_range_expected_decl : Error<
"for range declaration must declare a variable">;
def err_argument_required_after_attribute : Error<
@@ -303,6 +316,8 @@ def err_expected_class_name_not_template :
Error<"'typename' is redundant; base classes are implicitly types">;
def err_unspecified_vla_size_with_static : Error<
"'static' may not be used with an unspecified variable length array size">;
+def err_unspecified_size_with_static : Error<
+ "'static' may not be used without an array size">;
def warn_deprecated_register : Warning<
"'register' storage class specifier is deprecated">,
InGroup<DeprecatedRegister>;
@@ -332,10 +347,12 @@ def err_invalid_vector_decl_spec_combination : Error<
def err_invalid_pixel_decl_spec_combination : Error<
"'__pixel' must be preceded by '__vector'. "
"'%0' declaration specifier not allowed here">;
-def err_invalid_vector_decl_spec : Error<
- "cannot use '%0' with '__vector'">;
def err_invalid_vector_bool_decl_spec : Error<
"cannot use '%0' with '__vector bool'">;
+def err_invalid_vector_double_decl_spec : Error <
+ "use of 'double' with '__vector' requires VSX support to be enabled (available on the POWER7 or later)">;
+def err_invalid_vector_long_double_decl_spec : Error<
+ "cannot use 'long double' with '__vector'">;
def warn_vector_long_decl_spec_combination : Warning<
"Use of 'long' with '__vector' is deprecated">, InGroup<Deprecated>;
def err_friend_invalid_in_context : Error<
@@ -363,6 +380,8 @@ def err_function_definition_not_allowed : Error<
"function definition is not allowed here">;
def err_expected_end_of_enumerator : Error<
"expected '= constant-expression' or end of enumerator definition">;
+def err_expected_coloncolon_after_super : Error<
+ "expected '::' after '__super'">;
/// Objective-C parser diagnostics
def err_expected_minus_or_plus : Error<
@@ -477,6 +496,8 @@ def ext_ellipsis_exception_spec : Extension<
InGroup<Microsoft>;
def err_dynamic_and_noexcept_specification : Error<
"cannot have both throw() and noexcept() clause on the same function">;
+def err_except_spec_unparsed : Error<
+ "unexpected end of exception specification">;
def warn_cxx98_compat_noexcept_decl : Warning<
"noexcept specifications are incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
@@ -487,6 +508,8 @@ def err_constructor_bad_name : Error<
"missing return type for function %0; did you mean the constructor name %1?">;
def err_destructor_tilde_identifier : Error<
"expected a class name after '~' to name a destructor">;
+def err_destructor_tilde_scope : Error<
+ "'~' in destructor name should be after nested name specifier">;
def err_destructor_template_id : Error<
"destructor name %0 does not refer to a template">;
def err_default_arg_unparsed : Error<
@@ -498,11 +521,24 @@ def note_bracket_depth : Note<
def err_misplaced_ellipsis_in_declaration : Error<
"'...' must %select{immediately precede declared identifier|"
"be innermost component of anonymous pack declaration}0">;
+def warn_misplaced_ellipsis_vararg : Warning<
+ "'...' in this location creates a C-style varargs function"
+ "%select{, not a function parameter pack|}0">,
+ InGroup<DiagGroup<"ambiguous-ellipsis">>;
+def note_misplaced_ellipsis_vararg_existing_ellipsis : Note<
+ "preceding '...' declares a function parameter pack">;
+def note_misplaced_ellipsis_vararg_add_ellipsis : Note<
+ "place '...' %select{immediately before declared identifier|here}0 "
+ "to declare a function parameter pack">;
+def note_misplaced_ellipsis_vararg_add_comma : Note<
+ "insert ',' before '...' to silence this warning">;
def ext_abstract_pack_declarator_parens : ExtWarn<
"ISO C++11 requires a parenthesized pack declaration to have a name">,
InGroup<DiagGroup<"anonymous-pack-parens">>;
def err_function_is_not_record : Error<
"unexpected %0 in function call; perhaps remove the %0?">;
+def err_super_in_using_declaration : Error<
+ "'__super' cannot be used with a using declaration">;
// C++ derived classes
def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">;
@@ -529,6 +565,10 @@ def warn_cxx98_compat_noexcept_expr : Warning<
def warn_cxx98_compat_nullptr : Warning<
"'nullptr' is incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore;
+def warn_cxx14_compat_attribute : Warning<
+ "attributes on %select{a namespace|an enumerator}0 declaration are "
+ "incompatible with C++ standards before C++1z">,
+ InGroup<CXXPre1zCompat>, DefaultIgnore;
def warn_cxx98_compat_alignas : Warning<"'alignas' is incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
def warn_cxx98_compat_attribute : Warning<
@@ -564,6 +604,8 @@ def err_ms_property_expected_accessor_name : Error<
"expected name of accessor method">;
def err_ms_property_expected_comma_or_rparen : Error<
"expected ',' or ')' at end of property accessor list">;
+def err_ms_property_initializer : Error<
+ "property declaration cannot have an in-class initializer">;
/// C++ Templates
def err_expected_template : Error<"expected template">;
@@ -576,7 +618,7 @@ def err_class_on_template_template_param : Error<
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<
+def warn_cxx14_compat_template_template_param_typename : Warning<
"template template parameter using 'typename' is "
"incompatible with C++ standards before C++1z">,
InGroup<CXXPre1zCompat>, DefaultIgnore;
@@ -597,14 +639,16 @@ def warn_cxx11_right_shift_in_template_arg : Warning<
def warn_cxx98_compat_two_right_angle_brackets : Warning<
"consecutive right angle brackets are incompatible with C++98 (use '> >')">,
InGroup<CXX98Compat>, DefaultIgnore;
+def err_templated_invalid_declaration : Error<
+ "a static_assert declaration cannot be a template">;
def err_multiple_template_declarators : Error<
- "%select{|a template declaration|an explicit template specialization|"
- "an explicit template instantiation}0 can "
- "only %select{|declare|declare|instantiate}0 a single entity">;
+ "%select{|a template declaration|an explicit template specialization|"
+ "an explicit template instantiation}0 can "
+ "only %select{|declare|declare|instantiate}0 a single entity">;
def err_explicit_instantiation_with_definition : Error<
- "explicit template instantiation cannot have a definition; if this "
- "definition is meant to be an explicit specialization, add '<>' after the "
- "'template' keyword">;
+ "explicit template instantiation cannot have a definition; if this "
+ "definition is meant to be an explicit specialization, add '<>' after the "
+ "'template' keyword">;
def err_template_defn_explicit_instantiation : Error<
"%select{function|class|variable}0 cannot be defined in an explicit instantiation; if this "
"declaration is meant to be a %select{function|class|variable}0 definition, remove the 'template' keyword">;
@@ -612,7 +656,7 @@ def err_friend_explicit_instantiation : Error<
"friend cannot be declared in an explicit instantiation; if this "
"declaration is meant to be a friend declaration, remove the 'template' keyword">;
def err_explicit_instantiation_enum : Error<
- "enumerations cannot be explicitly instantiated">;
+ "enumerations cannot be explicitly instantiated">;
def err_expected_template_parameter : Error<"expected template parameter">;
def err_missing_dependent_template_keyword : Error<
@@ -654,7 +698,18 @@ def err_explicit_spec_non_template : Error<
def err_default_template_template_parameter_not_template : Error<
"default template argument for a template template parameter must be a class "
"template">;
-
+
+def ext_fold_expression : ExtWarn<
+ "pack fold expression is a C++1z extension">,
+ InGroup<CXX1z>;
+def warn_cxx14_compat_fold_expression : Warning<
+ "pack fold expression is incompatible with C++ standards before C++1z">,
+ InGroup<CXXPre1zCompat>, DefaultIgnore;
+def err_expected_fold_operator : Error<
+ "expected a foldable binary operator in fold expression">;
+def err_fold_operator_mismatch : Error<
+ "operators in fold expression must be the same">;
+
def err_ctor_init_missing_comma : Error<
"missing ',' between base or member initializers">;
@@ -699,7 +754,7 @@ def err_alias_declaration_not_identifier : Error<
"name defined in alias declaration must be an identifier">;
def err_alias_declaration_specialization : Error<
"%select{partial specialization|explicit specialization|explicit instantiation}0 of alias templates is not permitted">;
-
+
// C++11 override control
def ext_override_control_keyword : ExtWarn<
"'%0' keyword is a C++11 extension">, InGroup<CXX11>;
@@ -751,6 +806,9 @@ def err_lambda_missing_parens : Error<
// Availability attribute
def err_expected_version : Error<
"expected a version of the form 'major[.minor[.subminor]]'">;
+def warn_expected_consistent_version_separator : Warning<
+ "use same version number separators '_' or '.'; as in "
+ "'major[.minor[.subminor]]'">, InGroup<Availability>;
def err_zero_version : Error<
"version number must have non-zero major, minor, or sub-minor version">;
def err_availability_expected_platform : Error<
@@ -818,7 +876,7 @@ 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">;
+ "missing argument to '#pragma %0'%select{|; expected %2}1">;
// - #pragma options
def warn_pragma_options_expected_align : Warning<
"expected 'align' following '#pragma options' - ignored">,
@@ -878,8 +936,8 @@ 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<
- "OpenCL does not support the '%0' storage class specifier">;
+def err_opencl_unknown_type_specifier : Error<
+ "OpenCL does not support the '%0' %select{type qualifier|storage class specifier}1">;
// OpenCL EXTENSION pragma (OpenCL 1.1 [9.1])
def warn_pragma_expected_colon : Warning<
@@ -923,9 +981,14 @@ 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_missing_argument : Error<
+ "missing argument; expected %select{an integer value|"
+ "'%select{enable|full}1' or 'disable'}0">;
def err_pragma_loop_invalid_option : Error<
"%select{invalid|missing}0 option%select{ %1|}0; expected vectorize, "
"vectorize_width, interleave, interleave_count, unroll, or unroll_count">;
+def err_pragma_invalid_keyword : Error<
+ "invalid argument; expected '%select{enable|full}0' or 'disable'">;
// Pragma unroll support.
def warn_pragma_unroll_cuda_value_in_parens : Warning<
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 1665a45e2cbf..8966c55d0963 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -64,6 +64,9 @@ def err_typecheck_converted_constant_expression : Error<
"value of type %0 is not implicitly convertible to %1">;
def err_typecheck_converted_constant_expression_disallowed : Error<
"conversion from %0 to %1 is not allowed in a converted constant expression">;
+def err_typecheck_converted_constant_expression_indirect : Error<
+ "conversion from %0 to %1 in converted constant expression would "
+ "bind reference to a temporary">;
def err_expr_not_cce : Error<
"%select{case value|enumerator value|non-type template argument|array size}0 "
"is not a constant expression">;
@@ -84,6 +87,9 @@ def note_ice_conversion_here : Note<
def err_ice_ambiguous_conversion : Error<
"ambiguous conversion from type %0 to an integral or unscoped "
"enumeration type">;
+def err_ice_too_large : Error<
+ "integer constant expression evaluates to value %0 that cannot be "
+ "represented in a %1-bit %select{signed|unsigned}2 integer type">;
// Semantic analysis of constant literals.
def ext_predef_outside_function : Warning<
@@ -172,6 +178,9 @@ def warn_unused_parameter : Warning<"unused parameter %0">,
InGroup<UnusedParameter>, DefaultIgnore;
def warn_unused_variable : Warning<"unused variable %0">,
InGroup<UnusedVariable>, DefaultIgnore;
+def warn_unused_local_typedef : Warning<
+ "unused %select{typedef|type alias}0 %1">,
+ InGroup<UnusedLocalTypedef>, DefaultIgnore;
def warn_unused_property_backing_ivar :
Warning<"ivar %0 which backs the property is not "
"referenced in this property's accessor">,
@@ -445,9 +454,13 @@ def note_strncat_wrong_size : Note<
"the terminating null byte">;
def warn_assume_side_effects : Warning<
- "the argument to __assume has side effects that will be discarded">,
+ "the argument to %0 has side effects that will be discarded">,
InGroup<DiagGroup<"assume">>;
+def warn_memcpy_chk_overflow : Warning<
+ "%0 will always overflow destination buffer">,
+ InGroup<DiagGroup<"builtin-memcpy-chk-size">>;
+
/// main()
// static main() is not an error in C, just in C++.
def warn_static_main : Warning<"'main' should not be declared static">,
@@ -521,6 +534,11 @@ def warn_cxx_ms_struct :
"with base classes or virtual functions">,
DefaultError, InGroup<IncompatibleMSStruct>;
def err_section_conflict : Error<"%0 causes a section type conflict with %1">;
+def err_no_base_classes : Error<"invalid use of '__super', %0 has no base classes">;
+def err_invalid_super_scope : Error<"invalid use of '__super', "
+ "this keyword can only be used inside class or member function scope">;
+def err_super_in_lambda_unsupported : Error<
+ "use of '__super' inside a lambda is unsupported">;
def warn_pragma_unused_undeclared_var : Warning<
"undeclared variable %0 used as an argument for '#pragma unused'">,
@@ -536,10 +554,10 @@ 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_invalid_argument_type : Error<
+ "invalid argument of type %0; expected an integer type">;
+def err_pragma_loop_invalid_argument_value : Error<
+ "%select{invalid value '%0'; must be positive|value '%0' is too large}1">;
def err_pragma_loop_compatibility : Error<
"%select{incompatible|duplicate}0 directives '%1' and '%2'">;
def err_pragma_loop_precedes_nonloop : Error<
@@ -563,14 +581,19 @@ def err_protocol_has_circular_dependency : Error<
"protocol has circular dependency">;
def err_undeclared_protocol : Error<"cannot find protocol declaration for %0">;
def warn_undef_protocolref : Warning<"cannot find protocol definition for %0">;
+def warn_atprotocol_protocol : Warning<
+ "@protocol is using a forward protocol declaration of %0">, InGroup<AtProtocol>;
def warn_readonly_property : Warning<
"attribute 'readonly' of property %0 restricts attribute "
- "'readwrite' of property inherited from %1">;
+ "'readwrite' of property inherited from %1">,
+ InGroup<PropertyAttr>;
def warn_property_attribute : Warning<
- "'%1' attribute on property %0 does not match the property inherited from %2">;
+ "'%1' attribute on property %0 does not match the property inherited from %2">,
+ InGroup<PropertyAttr>;
def warn_property_types_are_incompatible : Warning<
- "property type %0 is incompatible with type %1 inherited from %2">;
+ "property type %0 is incompatible with type %1 inherited from %2">,
+ InGroup<DiagGroup<"incompatible-property-type">>;
def warn_protocol_property_mismatch : Warning<
"property of type %0 was selected for synthesis">,
InGroup<DiagGroup<"protocol-property-synthesis-ambiguity">>;
@@ -587,6 +610,8 @@ def note_class_declared : Note<
"class is declared here">;
def note_receiver_class_declared : Note<
"receiver is instance of class declared here">;
+def note_receiver_expr_here : Note<
+ "receiver expression is here">;
def note_receiver_is_id : Note<
"receiver is treated with 'id' type for purpose of method lookup">;
def note_suppressed_class_declare : Note<
@@ -696,7 +721,8 @@ def warn_implements_nscopying : Warning<
"default assign attribute on property %0 which implements "
"NSCopying protocol is not appropriate with -fobjc-gc[-only]">;
-def warn_multiple_method_decl : Warning<"multiple methods named %0 found">;
+def warn_multiple_method_decl : Warning<"multiple methods named %0 found">,
+ InGroup<ObjCMultipleMethodNames>;
def warn_strict_multiple_method_decl : Warning<
"multiple methods named %0 found">, InGroup<StrictSelector>, DefaultIgnore;
def warn_accessor_property_type_mismatch : Warning<
@@ -710,6 +736,11 @@ def err_duplicate_method_decl : Error<"duplicate declaration of method %0">;
def warn_duplicate_method_decl :
Warning<"multiple declarations of method %0 found and ignored">,
InGroup<MethodDuplicate>, DefaultIgnore;
+def warn_objc_cdirective_format_string :
+ Warning<"using %0 directive in %select{NSString|CFString}1 "
+ "which is being passed as a formatting argument to the formatting "
+ "%select{method|CFfunction}2">,
+ InGroup<ObjCCStringFormat>, DefaultIgnore;
def err_objc_var_decl_inclass :
Error<"cannot declare variable inside @interface or @protocol">;
def error_missing_method_context : Error<
@@ -738,7 +769,8 @@ def warn_objc_property_default_assign_on_object : Warning<
"default property attribute 'assign' not appropriate for non-GC object">,
InGroup<ObjCPropertyNoAttribute>;
def warn_property_attr_mismatch : Warning<
- "property attribute in class extension does not match the primary class">;
+ "property attribute in class extension does not match the primary class">,
+ InGroup<PropertyAttr>;
def warn_property_implicitly_mismatched : Warning <
"primary property declaration is implicitly strong while redeclaration "
"in class extension is weak">,
@@ -778,6 +810,11 @@ def warn_no_autosynthesis_property : Warning<
"%0 because it is 'readwrite' but it will be synthesized 'readonly' "
"via another property">,
InGroup<ObjCNoPropertyAutoSynthesis>;
+def warn_autosynthesis_property_in_superclass : Warning<
+ "auto property synthesis will not synthesize property "
+ "%0; it will be implemented by its superclass, use @dynamic to "
+ "acknowledge intention">,
+ InGroup<ObjCNoPropertyAutoSynthesis>;
def warn_autosynthesis_property_ivar_match :Warning<
"autosynthesized property %0 will use %select{|synthesized}1 instance variable "
"%2, not existing instance variable %3">,
@@ -927,7 +964,7 @@ def err_static_assert_expression_is_not_constant : Error<
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<
+def warn_cxx14_compat_static_assert_no_message : Warning<
"static_assert with no message is incompatible with C++ standards before C++1z">,
DefaultIgnore, InGroup<CXXPre1zCompat>;
@@ -1085,6 +1122,8 @@ def warn_missing_exception_specification : Warning<
"%0 is missing exception specification '%1'">;
def err_noexcept_needs_constant_expression : Error<
"argument to noexcept specifier must be a constant expression">;
+def err_exception_spec_not_parsed : Error<
+ "exception specification is not available until end of class definition">;
// C++ access checking
def err_class_redeclared_with_different_access : Error<
@@ -1098,7 +1137,7 @@ def ext_ms_using_declaration_inaccessible : ExtWarn<
def err_access_ctor : Error<
"calling a %select{private|protected}0 constructor of class %2">,
AccessControl;
-def ext_rvalue_to_reference_access_ctor : ExtWarn<
+def ext_rvalue_to_reference_access_ctor : Extension<
"C++98 requires an accessible copy constructor for class %2 when binding "
"a reference to a temporary; was %select{private|protected}0">,
AccessControl, InGroup<BindToTemporaryCopy>;
@@ -1462,6 +1501,9 @@ def note_uninit_reference_member : Note<
"uninitialized reference member is here">;
def warn_field_is_uninit : Warning<"field %0 is uninitialized when used here">,
InGroup<Uninitialized>;
+def warn_base_class_is_uninit : Warning<
+ "base class %0 is uninitialized when used here to access %q1">,
+ InGroup<Uninitialized>;
def warn_reference_field_is_uninit : Warning<
"reference %0 is not yet bound to a value when used here">,
InGroup<Uninitialized>;
@@ -1505,6 +1547,9 @@ def note_block_var_fixit_add_initialization : Note<
def note_in_omitted_aggregate_initializer : Note<
"in implicit initialization of %select{array element %1|field %1}0 "
"with omitted initializer">;
+def note_in_reference_temporary_list_initializer : Note<
+ "in initialization of temporary of type %0 created to "
+ "list-initialize this reference">;
def note_var_fixit_add_initialization : Note<
"initialize the variable %0 to silence this warning">;
def note_uninit_fixit_remove_cond : Note<
@@ -1522,7 +1567,7 @@ def err_temp_copy_no_viable : Error<
"returning object|throwing object|copying member subobject|copying array "
"element|allocating object|copying temporary|initializing base subobject|"
"initializing vector element|capturing value}0 of type %1">;
-def ext_rvalue_to_reference_temp_copy_no_viable : ExtWarn<
+def ext_rvalue_to_reference_temp_copy_no_viable : Extension<
"no viable constructor %select{copying variable|copying parameter|"
"returning object|throwing object|copying member subobject|copying array "
"element|allocating object|copying temporary|initializing base subobject|"
@@ -1594,9 +1639,9 @@ def err_auto_new_ctor_multiple_expressions : Error<
"new expression for type %0 contains multiple constructor arguments">;
def err_auto_missing_trailing_return : Error<
"'auto' return without trailing return type; deduced return types are a "
- "C++1y extension">;
+ "C++14 extension">;
def err_deduced_return_type : Error<
- "deduced return types are a C++1y extension">;
+ "deduced return types are a C++14 extension">;
def err_trailing_return_without_auto : Error<
"function with trailing return type must specify return type 'auto', not %0">;
def err_trailing_return_in_parens : Error<
@@ -1656,6 +1701,9 @@ def override_keyword_hides_virtual_member_function : Error<
"%select{function|functions}1">;
def err_function_marked_override_not_overriding : Error<
"%0 marked 'override' but does not override any member functions">;
+def warn_function_marked_not_override_overriding : Warning &